diff options
author | Brad King <brad.king@kitware.com> | 2017-09-14 11:39:08 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2017-09-14 11:39:24 (GMT) |
commit | 01b9d039e71aaaf69cf23330fc4129e888e40ea0 (patch) | |
tree | aa45ef102376d63ecc7789fedc87bb03dba2572f /Source | |
parent | 9c7bf6974f7e50e795e0ca960834909e14cdd7a0 (diff) | |
parent | 31f73eb12dd0888efc61c0333539d1354c7268ce (diff) | |
download | CMake-01b9d039e71aaaf69cf23330fc4129e888e40ea0.zip CMake-01b9d039e71aaaf69cf23330fc4129e888e40ea0.tar.gz CMake-01b9d039e71aaaf69cf23330fc4129e888e40ea0.tar.bz2 |
Merge topic 'get_filename_component-fix-program-split'
31f73eb1 get_filename_component: Revise PROGRAM/PROGRAM_ARGS split semantics
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !1251
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmGetFilenameComponentCommand.cxx | 25 | ||||
-rw-r--r-- | Source/cmSystemTools.cxx | 50 | ||||
-rw-r--r-- | Source/cmSystemTools.h | 5 |
3 files changed, 79 insertions, 1 deletions
diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index c23684c..1b358ab 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -60,7 +60,30 @@ bool cmGetFilenameComponentCommand::InitialPass( } } } - cmSystemTools::SplitProgramFromArgs(filename, result, programArgs); + + // First assume the path to the program was specified with no + // arguments and with no quoting or escaping for spaces. + // Only bother doing this if there is non-whitespace. + if (!cmSystemTools::TrimWhitespace(filename).empty()) { + result = cmSystemTools::FindProgram(filename); + } + + // If that failed then assume a command-line string was given + // and split the program part from the rest of the arguments. + if (result.empty()) { + std::string program; + if (cmSystemTools::SplitProgramFromArgs(filename, program, + programArgs)) { + if (cmSystemTools::FileExists(program)) { + result = program; + } else { + result = cmSystemTools::FindProgram(program); + } + } + if (result.empty()) { + programArgs.clear(); + } + } } else if (args[2] == "EXT") { result = cmSystemTools::GetFilenameExtension(filename); } else if (args[2] == "NAME_WE") { diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index fd9fb5e..4118664 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -603,6 +603,56 @@ std::vector<std::string> cmSystemTools::ParseArguments(const char* command) return args; } +bool cmSystemTools::SplitProgramFromArgs(std::string const& command, + std::string& program, + std::string& args) +{ + const char* c = command.c_str(); + + // Skip leading whitespace. + while (isspace(static_cast<unsigned char>(*c))) { + ++c; + } + + // Parse one command-line element up to an unquoted space. + bool in_escape = false; + bool in_double = false; + bool in_single = false; + for (; *c; ++c) { + if (in_single) { + if (*c == '\'') { + in_single = false; + } else { + program += *c; + } + } else if (in_escape) { + in_escape = false; + program += *c; + } else if (*c == '\\') { + in_escape = true; + } else if (in_double) { + if (*c == '"') { + in_double = false; + } else { + program += *c; + } + } else if (*c == '"') { + in_double = true; + } else if (*c == '\'') { + in_single = true; + } else if (isspace(static_cast<unsigned char>(*c))) { + break; + } else { + program += *c; + } + } + + // The remainder of the command line holds unparsed arguments. + args = c; + + return !in_single && !in_escape && !in_double; +} + size_t cmSystemTools::CalculateCommandLineLengthLimit() { size_t sz = diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 9bec361..e7082e6 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -255,6 +255,11 @@ public: static void ParseUnixCommandLine(const char* command, std::vector<std::string>& args); + /** Split a command-line string into the parsed command and the unparsed + arguments. Returns false on unfinished quoting or escaping. */ + static bool SplitProgramFromArgs(std::string const& command, + std::string& program, std::string& args); + /** * Handle response file in an argument list and return a new argument list * **/ |