OpenCL apps can quote arguments they pass to the OpenCL compiler, most commonly include paths containing spaces. If the OpenCL compiler was called via a shell, the shell would remove (single or double) quotes before passing the argument to the compiler. Since we call Clang as a library, we have to remove quotes before passing the argument. --- .../state_trackers/clover/llvm/invocation.cpp | 41 +++++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-)
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp index e2cadda..d389a76 100644 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp @@ -147,12 +147,43 @@ namespace { // Parse the compiler options: std::vector<std::string> opts_array; - std::istringstream ss(opts); + std::ostringstream builder; + + // 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 skip_space = false; + bool in_quote_double = false; + bool in_quote_single = false; + for (auto pos = std::begin(opts); pos != std::end(opts); ++pos) { + if (escape_next) { + builder.put(*pos); + escape_next = false; + } else if (*pos == '\\') { + escape_next = true; + } else if (*pos == '"' && !in_quote_single) { + in_quote_double = !in_quote_double; + skip_space = !skip_space; + } else if (*pos == '\'' && !in_quote_double) { + in_quote_single = !in_quote_single; + skip_space = !skip_space; + } else if (*pos == ' ' && !skip_space && builder.tellp() > 0) { + opts_array.emplace_back(builder.str()); + builder.str(""); + } else if (*pos != ' ' || skip_space) { + builder.put(*pos); + } + } + if (builder.tellp() > 0) { + opts_array.emplace_back(builder.str()); + } - while (!ss.eof()) { - std::string opt; - getline(ss, opt, ' '); - opts_array.push_back(opt); + if (in_quote_double || in_quote_single) { + throw error(CL_INVALID_COMPILER_OPTIONS); } opts_array.push_back(name); -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev