| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file Copyright.txt or https://cmake.org/licensing for details.  */
 
- #include "cmOutputConverter.h"
 
- #include <algorithm>
 
- #include <cassert>
 
- #include <cctype>
 
- #include <set>
 
- #ifdef _WIN32
 
- #  include <unordered_map>
 
- #  include <utility>
 
- #endif
 
- #include "cmList.h"
 
- #include "cmState.h"
 
- #include "cmStateDirectory.h"
 
- #include "cmSystemTools.h"
 
- #include "cmValue.h"
 
- namespace {
 
- bool PathEqOrSubDir(std::string const& a, std::string const& b)
 
- {
 
-   return (cmSystemTools::ComparePath(a, b) ||
 
-           cmSystemTools::IsSubDirectory(a, b));
 
- }
 
- }
 
- cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot)
 
-   : StateSnapshot(snapshot)
 
- {
 
-   assert(this->StateSnapshot.IsValid());
 
-   this->ComputeRelativePathTopSource();
 
-   this->ComputeRelativePathTopBinary();
 
-   this->ComputeRelativePathTopRelation();
 
- }
 
- void cmOutputConverter::ComputeRelativePathTopSource()
 
- {
 
-   // Walk up the buildsystem directory tree to find the highest source
 
-   // directory that contains the current source directory.
 
-   cmStateSnapshot snapshot = this->StateSnapshot;
 
-   for (cmStateSnapshot parent = snapshot.GetBuildsystemDirectoryParent();
 
-        parent.IsValid(); parent = parent.GetBuildsystemDirectoryParent()) {
 
-     if (cmSystemTools::IsSubDirectory(
 
-           snapshot.GetDirectory().GetCurrentSource(),
 
-           parent.GetDirectory().GetCurrentSource())) {
 
-       snapshot = parent;
 
-     }
 
-   }
 
-   this->RelativePathTopSource = snapshot.GetDirectory().GetCurrentSource();
 
- }
 
- void cmOutputConverter::ComputeRelativePathTopBinary()
 
- {
 
-   // Walk up the buildsystem directory tree to find the highest binary
 
-   // directory that contains the current binary directory.
 
-   cmStateSnapshot snapshot = this->StateSnapshot;
 
-   for (cmStateSnapshot parent = snapshot.GetBuildsystemDirectoryParent();
 
-        parent.IsValid(); parent = parent.GetBuildsystemDirectoryParent()) {
 
-     if (cmSystemTools::IsSubDirectory(
 
-           snapshot.GetDirectory().GetCurrentBinary(),
 
-           parent.GetDirectory().GetCurrentBinary())) {
 
-       snapshot = parent;
 
-     }
 
-   }
 
-   this->RelativePathTopBinary = snapshot.GetDirectory().GetCurrentBinary();
 
- }
 
- void cmOutputConverter::ComputeRelativePathTopRelation()
 
- {
 
-   if (cmSystemTools::ComparePath(this->RelativePathTopSource,
 
-                                  this->RelativePathTopBinary)) {
 
-     this->RelativePathTopRelation = TopRelation::InSource;
 
-   } else if (cmSystemTools::IsSubDirectory(this->RelativePathTopBinary,
 
-                                            this->RelativePathTopSource)) {
 
-     this->RelativePathTopRelation = TopRelation::BinInSrc;
 
-   } else if (cmSystemTools::IsSubDirectory(this->RelativePathTopSource,
 
-                                            this->RelativePathTopBinary)) {
 
-     this->RelativePathTopRelation = TopRelation::SrcInBin;
 
-   } else {
 
-     this->RelativePathTopRelation = TopRelation::Separate;
 
-   }
 
- }
 
- std::string const& cmOutputConverter::GetRelativePathTopSource() const
 
- {
 
-   return this->RelativePathTopSource;
 
- }
 
- std::string const& cmOutputConverter::GetRelativePathTopBinary() const
 
- {
 
-   return this->RelativePathTopBinary;
 
- }
 
- void cmOutputConverter::SetRelativePathTop(std::string const& topSource,
 
-                                            std::string const& topBinary)
 
- {
 
-   this->RelativePathTopSource = topSource;
 
-   this->RelativePathTopBinary = topBinary;
 
-   this->ComputeRelativePathTopRelation();
 
- }
 
- std::string cmOutputConverter::MaybeRelativeTo(
 
-   std::string const& local_path, std::string const& remote_path) const
 
- {
 
-   bool localInBinary = PathEqOrSubDir(local_path, this->RelativePathTopBinary);
 
-   bool remoteInBinary =
 
-     PathEqOrSubDir(remote_path, this->RelativePathTopBinary);
 
-   bool localInSource = PathEqOrSubDir(local_path, this->RelativePathTopSource);
 
-   bool remoteInSource =
 
-     PathEqOrSubDir(remote_path, this->RelativePathTopSource);
 
-   switch (this->RelativePathTopRelation) {
 
-     case TopRelation::Separate:
 
-       // Checks are independent.
 
-       break;
 
-     case TopRelation::BinInSrc:
 
-       localInSource = localInSource && !localInBinary;
 
-       remoteInSource = remoteInSource && !remoteInBinary;
 
-       break;
 
-     case TopRelation::SrcInBin:
 
-       localInBinary = localInBinary && !localInSource;
 
-       remoteInBinary = remoteInBinary && !remoteInSource;
 
-       break;
 
-     case TopRelation::InSource:
 
-       // Checks are identical.
 
-       break;
 
-   };
 
-   bool const bothInBinary = localInBinary && remoteInBinary;
 
-   bool const bothInSource = localInSource && remoteInSource;
 
-   if (bothInBinary || bothInSource) {
 
-     return cmSystemTools::ForceToRelativePath(local_path, remote_path);
 
-   }
 
-   return remote_path;
 
- }
 
- std::string cmOutputConverter::MaybeRelativeToTopBinDir(
 
-   std::string const& path) const
 
- {
 
-   return this->MaybeRelativeTo(this->GetState()->GetBinaryDirectory(), path);
 
- }
 
- std::string cmOutputConverter::MaybeRelativeToCurBinDir(
 
-   std::string const& path) const
 
- {
 
-   return this->MaybeRelativeTo(
 
-     this->StateSnapshot.GetDirectory().GetCurrentBinary(), path);
 
- }
 
- std::string cmOutputConverter::ConvertToOutputForExisting(
 
-   const std::string& remote, OutputFormat format, bool useWatcomQuote) const
 
- {
 
- #ifdef _WIN32
 
-   // Cache the Short Paths since we only convert the same few paths anyway and
 
-   // calling `GetShortPathNameW` is really expensive.
 
-   static std::unordered_map<std::string, std::string> shortPathCache{};
 
-   // 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() &&
 
-       remote.find_first_of(" #") != std::string::npos &&
 
-       cmSystemTools::FileExists(remote)) {
 
-     std::string shortPath = [&]() {
 
-       auto cachedShortPathIt = shortPathCache.find(remote);
 
-       if (cachedShortPathIt != shortPathCache.end()) {
 
-         return cachedShortPathIt->second;
 
-       }
 
-       std::string tmp{};
 
-       cmSystemTools::GetShortPath(remote, tmp);
 
-       shortPathCache[remote] = tmp;
 
-       return tmp;
 
-     }();
 
-     return this->ConvertToOutputFormat(shortPath, format, useWatcomQuote);
 
-   }
 
- #endif
 
-   // Otherwise, perform standard conversion.
 
-   return this->ConvertToOutputFormat(remote, format, useWatcomQuote);
 
- }
 
- std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source,
 
-                                                      OutputFormat format,
 
-                                                      bool useWatcomQuote) const
 
- {
 
-   std::string result(source);
 
-   // Convert it to an output path.
 
-   if (format == SHELL || format == NINJAMULTI) {
 
-     result = this->ConvertDirectorySeparatorsForShell(source);
 
-     result = this->EscapeForShell(result, true, false, useWatcomQuote,
 
-                                   format == NINJAMULTI);
 
-   } else if (format == RESPONSE) {
 
-     result =
 
-       this->EscapeForShell(result, false, false, useWatcomQuote, false, true);
 
-   }
 
-   return result;
 
- }
 
- std::string cmOutputConverter::ConvertDirectorySeparatorsForShell(
 
-   cm::string_view source) const
 
- {
 
-   std::string result(source);
 
-   // 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(), '/', '\\');
 
-   }
 
-   return result;
 
- }
 
- static bool cmOutputConverterIsShellOperator(cm::string_view str)
 
- {
 
-   static std::set<cm::string_view> const shellOperators{
 
-     "<", ">", "<<", ">>", "|", "||", "&&", "&>", "1>", "2>", "2>&1", "1>&2"
 
-   };
 
-   return (shellOperators.count(str) != 0);
 
- }
 
- std::string cmOutputConverter::EscapeForShell(cm::string_view str,
 
-                                               bool makeVars, bool forEcho,
 
-                                               bool useWatcomQuote,
 
-                                               bool unescapeNinjaConfiguration,
 
-                                               bool forResponse) const
 
- {
 
-   // Do not escape shell operators.
 
-   if (cmOutputConverterIsShellOperator(str)) {
 
-     return std::string(str);
 
-   }
 
-   // Compute the flags for the target shell environment.
 
-   int flags = 0;
 
-   if (this->GetState()->UseWindowsVSIDE()) {
 
-     flags |= Shell_Flag_VSIDE;
 
-   } else if (!this->LinkScriptShell) {
 
-     flags |= Shell_Flag_Make;
 
-   }
 
-   if (unescapeNinjaConfiguration) {
 
-     flags |= Shell_Flag_UnescapeNinjaConfiguration;
 
-   }
 
-   if (makeVars) {
 
-     flags |= Shell_Flag_AllowMakeVariables;
 
-   }
 
-   if (forEcho) {
 
-     flags |= Shell_Flag_EchoWindows;
 
-   }
 
-   if (useWatcomQuote) {
 
-     flags |= Shell_Flag_WatcomQuote;
 
-   }
 
-   if (forResponse) {
 
-     flags |= Shell_Flag_IsResponse;
 
-   }
 
-   if (this->GetState()->UseWatcomWMake()) {
 
-     flags |= Shell_Flag_WatcomWMake;
 
-   }
 
-   if (this->GetState()->UseMinGWMake()) {
 
-     flags |= Shell_Flag_MinGWMake;
 
-   }
 
-   if (this->GetState()->UseNMake()) {
 
-     flags |= Shell_Flag_NMake;
 
-   }
 
-   if (!this->GetState()->UseWindowsShell()) {
 
-     flags |= Shell_Flag_IsUnix;
 
-   }
 
-   return Shell_GetArgument(str, flags);
 
- }
 
- std::string cmOutputConverter::EscapeForCMake(cm::string_view str,
 
-                                               WrapQuotes wrapQuotes)
 
- {
 
-   // Always double-quote the argument to take care of most escapes.
 
-   std::string result = (wrapQuotes == WrapQuotes::Wrap) ? "\"" : "";
 
-   for (const char c : str) {
 
-     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;
 
-     }
 
-   }
 
-   if (wrapQuotes == WrapQuotes::Wrap) {
 
-     result += "\"";
 
-   }
 
-   return result;
 
- }
 
- std::string cmOutputConverter::EscapeWindowsShellArgument(cm::string_view arg,
 
-                                                           int shell_flags)
 
- {
 
-   return Shell_GetArgument(arg, shell_flags);
 
- }
 
- cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
 
-   cm::string_view value)
 
- {
 
-   FortranFormat format = FortranFormatNone;
 
-   if (!value.empty()) {
 
-     for (std::string const& fi : cmList(value)) {
 
-       if (fi == "FIXED") {
 
-         format = FortranFormatFixed;
 
-       }
 
-       if (fi == "FREE") {
 
-         format = FortranFormatFree;
 
-       }
 
-     }
 
-   }
 
-   return format;
 
- }
 
- cmOutputConverter::FortranPreprocess cmOutputConverter::GetFortranPreprocess(
 
-   cm::string_view value)
 
- {
 
-   if (value.empty()) {
 
-     return FortranPreprocess::Unset;
 
-   }
 
-   return cmIsOn(value) ? FortranPreprocess::Needed
 
-                        : FortranPreprocess::NotNeeded;
 
- }
 
- void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell)
 
- {
 
-   this->LinkScriptShell = linkScriptShell;
 
- }
 
- cmState* cmOutputConverter::GetState() const
 
- {
 
-   return this->StateSnapshot.GetState();
 
- }
 
- /*
 
- Notes:
 
- Make variable replacements open a can of worms.  Sometimes they should
 
- be quoted and sometimes not.  Sometimes their replacement values are
 
- already quoted.
 
- VS variables cause problems.  In order to pass the referenced value
 
- with spaces the reference must be quoted.  If the variable value ends
 
- in a backslash then it will escape the ending quote!  In order to make
 
- the ending backslash appear we need this:
 
-   "$(InputDir)\"
 
- However if there is not a trailing backslash then this will put a
 
- quote in the value so we need:
 
-   "$(InputDir)"
 
- Make variable references are platform specific so we should probably
 
- just NOT quote them and let the listfile author deal with it.
 
- */
 
- /*
 
- TODO: For windows echo:
 
- To display a pipe (|) or redirection character (< or >) when using the
 
- echo command, use a caret character immediately before the pipe or
 
- redirection character (for example, ^>, ^<, or ^| ). If you need to
 
- use the caret character itself (^), use two in a row (^^).
 
- */
 
- /* Some helpers to identify character classes */
 
- static bool Shell_CharIsWhitespace(char c)
 
- {
 
-   return ((c == ' ') || (c == '\t'));
 
- }
 
- static bool Shell_CharNeedsQuotesOnUnix(char c)
 
- {
 
-   return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
 
-           (c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
 
-           (c == '<') || (c == '>') || (c == '|') || (c == '*') || (c == '^') ||
 
-           (c == '\\'));
 
- }
 
- static bool Shell_CharNeedsQuotesOnWindows(char c)
 
- {
 
-   return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
 
-           (c == '>') || (c == '|') || (c == '^'));
 
- }
 
- static bool Shell_CharIsMakeVariableName(char c)
 
- {
 
-   return c && (c == '_' || isalpha((static_cast<int>(c))));
 
- }
 
- bool cmOutputConverter::Shell_CharNeedsQuotes(char c, int flags)
 
- {
 
-   /* On Windows the built-in command shell echo never needs quotes.  */
 
-   if (!(flags & Shell_Flag_IsUnix) && (flags & Shell_Flag_EchoWindows)) {
 
-     return false;
 
-   }
 
-   /* On all platforms quotes are needed to preserve whitespace.  */
 
-   if (Shell_CharIsWhitespace(c)) {
 
-     return true;
 
-   }
 
-   /* Quote hyphens in response files */
 
-   if (flags & Shell_Flag_IsResponse) {
 
-     if (c == '-') {
 
-       return true;
 
-     }
 
-   }
 
-   if (flags & Shell_Flag_IsUnix) {
 
-     /* On UNIX several special characters need quotes to preserve them.  */
 
-     if (Shell_CharNeedsQuotesOnUnix(c)) {
 
-       return true;
 
-     }
 
-   } else {
 
-     /* On Windows several special characters need quotes to preserve them.  */
 
-     if (Shell_CharNeedsQuotesOnWindows(c)) {
 
-       return true;
 
-     }
 
-   }
 
-   return false;
 
- }
 
- cm::string_view::iterator cmOutputConverter::Shell_SkipMakeVariables(
 
-   cm::string_view::iterator c, cm::string_view::iterator end)
 
- {
 
-   while ((c != end && (c + 1) != end) && (*c == '$' && *(c + 1) == '(')) {
 
-     cm::string_view::iterator skip = c + 2;
 
-     while ((skip != end) && Shell_CharIsMakeVariableName(*skip)) {
 
-       ++skip;
 
-     }
 
-     if ((skip != end) && *skip == ')') {
 
-       c = skip + 1;
 
-     } else {
 
-       break;
 
-     }
 
-   }
 
-   return c;
 
- }
 
- /*
 
- Allowing make variable replacements opens a can of worms.  Sometimes
 
- they should be quoted and sometimes not.  Sometimes their replacement
 
- values are already quoted or contain escapes.
 
- Some Visual Studio variables cause problems.  In order to pass the
 
- referenced value with spaces the reference must be quoted.  If the
 
- variable value ends in a backslash then it will escape the ending
 
- quote!  In order to make the ending backslash appear we need this:
 
-   "$(InputDir)\"
 
- However if there is not a trailing backslash then this will put a
 
- quote in the value so we need:
 
-   "$(InputDir)"
 
- This macro decides whether we quote an argument just because it
 
- contains a make variable reference.  This should be replaced with a
 
- flag later when we understand applications of this better.
 
- */
 
- #define KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES 0
 
- bool cmOutputConverter::Shell_ArgumentNeedsQuotes(cm::string_view in,
 
-                                                   int flags)
 
- {
 
-   /* The empty string needs quotes.  */
 
-   if (in.empty()) {
 
-     return true;
 
-   }
 
-   /* Scan the string for characters that require quoting.  */
 
-   for (cm::string_view::iterator cit = in.begin(), cend = in.end();
 
-        cit != cend; ++cit) {
 
-     /* Look for $(MAKEVAR) syntax if requested.  */
 
-     if (flags & Shell_Flag_AllowMakeVariables) {
 
- #if KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES
 
-       cm::string_view::iterator skip = Shell_SkipMakeVariables(cit, cend);
 
-       if (skip != cit) {
 
-         /* We need to quote make variable references to preserve the
 
-            string with contents substituted in its place.  */
 
-         return true;
 
-       }
 
- #else
 
-       /* Skip over the make variable references if any are present.  */
 
-       cit = Shell_SkipMakeVariables(cit, cend);
 
-       /* Stop if we have reached the end of the string.  */
 
-       if (cit == cend) {
 
-         break;
 
-       }
 
- #endif
 
-     }
 
-     /* Check whether this character needs quotes.  */
 
-     if (Shell_CharNeedsQuotes(*cit, flags)) {
 
-       return true;
 
-     }
 
-   }
 
-   /* On Windows some single character arguments need quotes.  */
 
-   if (flags & Shell_Flag_IsUnix && in.size() == 1) {
 
-     char c = in[0];
 
-     if ((c == '?') || (c == '&') || (c == '^') || (c == '|') || (c == '#')) {
 
-       return true;
 
-     }
 
-   }
 
-   /* UNC paths in MinGW Makefiles need quotes.  */
 
-   if ((flags & Shell_Flag_MinGWMake) && (flags & Shell_Flag_Make)) {
 
-     if (in.size() > 1 && in[0] == '\\' && in[1] == '\\') {
 
-       return true;
 
-     }
 
-   }
 
-   return false;
 
- }
 
- std::string cmOutputConverter::Shell_GetArgument(cm::string_view in, int flags)
 
- {
 
-   /* Output will be at least as long as input string.  */
 
-   std::string out;
 
-   out.reserve(in.size());
 
-   /* Keep track of how many backslashes have been encountered in a row.  */
 
-   int windows_backslashes = 0;
 
-   /* Whether the argument must be quoted.  */
 
-   int needQuotes = Shell_ArgumentNeedsQuotes(in, flags);
 
-   if (needQuotes) {
 
-     /* Add the opening quote for this argument.  */
 
-     if (flags & Shell_Flag_WatcomQuote) {
 
-       if (flags & Shell_Flag_IsUnix) {
 
-         out += '"';
 
-       }
 
-       out += '\'';
 
-     } else {
 
-       out += '"';
 
-     }
 
-   }
 
-   /* Scan the string for characters that require escaping or quoting.  */
 
-   for (cm::string_view::iterator cit = in.begin(), cend = in.end();
 
-        cit != cend; ++cit) {
 
-     /* Look for $(MAKEVAR) syntax if requested.  */
 
-     if (flags & Shell_Flag_AllowMakeVariables) {
 
-       cm::string_view::iterator skip = Shell_SkipMakeVariables(cit, cend);
 
-       if (skip != cit) {
 
-         /* Copy to the end of the make variable references.  */
 
-         while (cit != skip) {
 
-           out += *cit++;
 
-         }
 
-         /* The make variable reference eliminates any escaping needed
 
-            for preceding backslashes.  */
 
-         windows_backslashes = 0;
 
-         /* Stop if we have reached the end of the string.  */
 
-         if (cit == cend) {
 
-           break;
 
-         }
 
-       }
 
-     }
 
-     /* Check whether this character needs escaping for the shell.  */
 
-     if (flags & Shell_Flag_IsUnix) {
 
-       /* On Unix a few special characters need escaping even inside a
 
-          quoted argument.  */
 
-       if (*cit == '\\' || *cit == '"' || *cit == '`' || *cit == '$') {
 
-         /* This character needs a backslash to escape it.  */
 
-         out += '\\';
 
-       }
 
-     } else if (flags & Shell_Flag_EchoWindows) {
 
-       /* On Windows the built-in command shell echo never needs escaping.  */
 
-     } else {
 
-       /* On Windows only backslashes and double-quotes need escaping.  */
 
-       if (*cit == '\\') {
 
-         /* Found a backslash.  It may need to be escaped later.  */
 
-         ++windows_backslashes;
 
-       } else if (*cit == '"') {
 
-         /* Found a double-quote.  Escape all immediately preceding
 
-            backslashes.  */
 
-         while (windows_backslashes > 0) {
 
-           --windows_backslashes;
 
-           out += '\\';
 
-         }
 
-         /* Add the backslash to escape the double-quote.  */
 
-         out += '\\';
 
-       } else {
 
-         /* We encountered a normal character.  This eliminates any
 
-            escaping needed for preceding backslashes.  */
 
-         windows_backslashes = 0;
 
-       }
 
-     }
 
-     /* Check whether this character needs escaping for a make tool.  */
 
-     if (*cit == '$') {
 
-       if (flags & Shell_Flag_Make) {
 
-         /* In Makefiles a dollar is written $$.  The make tool will
 
-            replace it with just $ before passing it to the shell.  */
 
-         out += "$$";
 
-       } else if (flags & Shell_Flag_VSIDE) {
 
-         /* In a VS IDE a dollar is written "$".  If this is written in
 
-            an un-quoted argument it starts a quoted segment, inserts
 
-            the $ and ends the segment.  If it is written in a quoted
 
-            argument it ends quoting, inserts the $ and restarts
 
-            quoting.  Either way the $ is isolated from surrounding
 
-            text to avoid looking like a variable reference.  */
 
-         out += "\"$\"";
 
-       } else {
 
-         /* Otherwise a dollar is written just $. */
 
-         out += '$';
 
-       }
 
-     } else if (*cit == '#') {
 
-       if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
 
-         /* In Watcom WMake makefiles a pound is written $#.  The make
 
-            tool will replace it with just # before passing it to the
 
-            shell.  */
 
-         out += "$#";
 
-       } else {
 
-         /* Otherwise a pound is written just #. */
 
-         out += '#';
 
-       }
 
-     } else if (*cit == '%') {
 
-       if ((flags & Shell_Flag_VSIDE) ||
 
-           ((flags & Shell_Flag_Make) &&
 
-            ((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) {
 
-         /* In the VS IDE, NMake, or MinGW make a percent is written %%.  */
 
-         out += "%%";
 
-       } else {
 
-         /* Otherwise a percent is written just %. */
 
-         out += '%';
 
-       }
 
-     } else if (*cit == ';') {
 
-       if (flags & Shell_Flag_VSIDE) {
 
-         /* In a VS IDE a semicolon is written ";".  If this is written
 
-            in an un-quoted argument it starts a quoted segment,
 
-            inserts the ; and ends the segment.  If it is written in a
 
-            quoted argument it ends quoting, inserts the ; and restarts
 
-            quoting.  Either way the ; is isolated.  */
 
-         out += "\";\"";
 
-       } else {
 
-         /* Otherwise a semicolon is written just ;. */
 
-         out += ';';
 
-       }
 
-     } else {
 
-       /* Store this character.  */
 
-       out += *cit;
 
-     }
 
-   }
 
-   if (needQuotes) {
 
-     /* Add enough backslashes to escape any trailing ones.  */
 
-     while (windows_backslashes > 0) {
 
-       --windows_backslashes;
 
-       out += '\\';
 
-     }
 
-     /* Add the closing quote for this argument.  */
 
-     if (flags & Shell_Flag_WatcomQuote) {
 
-       out += '\'';
 
-       if (flags & Shell_Flag_IsUnix) {
 
-         out += '"';
 
-       }
 
-     } else {
 
-       out += '"';
 
-     }
 
-   }
 
-   if (flags & Shell_Flag_UnescapeNinjaConfiguration) {
 
-     std::string ninjaConfigReplace;
 
-     if (flags & Shell_Flag_IsUnix) {
 
-       ninjaConfigReplace += '\\';
 
-     }
 
-     ninjaConfigReplace += "$${CONFIGURATION}";
 
-     cmSystemTools::ReplaceString(out, ninjaConfigReplace, "${CONFIGURATION}");
 
-   }
 
-   return out;
 
- }
 
 
  |