summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/clover
diff options
context:
space:
mode:
authorVedran Miletić <[email protected]>2016-09-28 17:11:43 +0200
committerFrancisco Jerez <[email protected]>2016-10-30 12:14:59 -0700
commite3272865c216933168e6c08766d266a33d0e1497 (patch)
treee985ca5c03785c57557fcd7f08f2029ccf04c76a /src/gallium/state_trackers/clover
parent2a4a86862c949055c71637429f6d5f2e725d07d8 (diff)
clover: Pass unquoted compiler arguments to Clang
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 v4: restore error throwing, clarify a comment Signed-off-by: Vedran Miletić <[email protected]> Reviewed-by: Francisco Jerez <[email protected]>
Diffstat (limited to 'src/gallium/state_trackers/clover')
-rw-r--r--src/gallium/state_trackers/clover/llvm/util.hpp40
1 files changed, 36 insertions, 4 deletions
diff --git a/src/gallium/state_trackers/clover/llvm/util.hpp b/src/gallium/state_trackers/clover/llvm/util.hpp
index 8db6f20e5a7..222becd614e 100644
--- a/src/gallium/state_trackers/clover/llvm/util.hpp
+++ b/src/gallium/state_trackers/clover/llvm/util.hpp
@@ -24,6 +24,7 @@
#ifndef CLOVER_LLVM_UTIL_HPP
#define CLOVER_LLVM_UTIL_HPP
+#include "core/error.hpp"
#include "util/u_debug.h"
#include <vector>
@@ -42,11 +43,42 @@ 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 quoted argument, most frequently the
+ // include path. This is useful so that path containing spaces is
+ // treated as a single argument instead of being split by the spaces.
+ // Additionally, the argument should also be unquoted before being
+ // passed to the compiler. We avoid using std::string::replace here to
+ // remove quotes, as the single and double quote characters can be a
+ // part of the file name.
+ 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());
+
+ if (in_quote_double || in_quote_single)
+ throw invalid_build_options_error();
return ss;
}