aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;
}