OpenCL apps can quote arguments they pass to the OpenCL compiler, most commonly include paths containing spaces.
If the Clang OpenCL compiler was called via a shell, the shell would split the arguments with respect to to quotes and then remove quotes before passing the arguments to the compiler. Since we call Clang as a library, we have to split the argument with respect to quotes and then remove quotes before passing the arguments. v2: move to tokenize(), remove throwing of CL_INVALID_COMPILER_OPTIONS v3: simplify parsing logic, use more C++11 --- src/gallium/state_trackers/clover/llvm/util.hpp | 33 ++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/gallium/state_trackers/clover/llvm/util.hpp b/src/gallium/state_trackers/clover/llvm/util.hpp index 8db6f20..c770dd8 100644 --- a/src/gallium/state_trackers/clover/llvm/util.hpp +++ b/src/gallium/state_trackers/clover/llvm/util.hpp @@ -42,11 +42,36 @@ namespace clover { inline std::vector<std::string> tokenize(const std::string &s) { std::vector<std::string> ss; - std::istringstream iss(s); - std::string t; + std::ostringstream oss; - while (getline(iss, t, ' ')) - ss.push_back(t); + // OpenCL programs can pass a single or double quoted argument, most + // frequently include path. This is useful so that the path containing + // spaces is treated as a single argument, but we should anyhow unquote + // quoted arguments before passing them to the compiler. + // We do not want to avoid using std::string::replace here, as include + // path can contain quotes in file names. + bool escape_next = false; + bool in_quote_double = false; + bool in_quote_single = false; + for (auto c : s) { + if (escape_next) { + oss.put(c); + escape_next = false; + } else if (c == '\\') { + escape_next = true; + } else if (c == '"' && !in_quote_single) { + in_quote_double = !in_quote_double; + } else if (c == '\'' && !in_quote_double) { + in_quote_single = !in_quote_single; + } else if (c != ' ' || in_quote_single || in_quote_double) { + oss.put(c); + } else if (oss.tellp() > 0) { + ss.emplace_back(oss.str()); + oss.str(""); + } + } + if (oss.tellp() > 0) + ss.emplace_back(oss.str()); return ss; } -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev