OC-11191 Correct escaping support for compiler arguments and defines

This commit is contained in:
Alexey Utkin
2014-12-01 19:53:53 +03:00
parent a449fe1158
commit 8eee5b6333
3 changed files with 31 additions and 6 deletions
@@ -99,11 +99,11 @@ public class CommandLineTokenizer extends StringTokenizer {
int i;
int quotationMarks = 0;
final StringBuffer buffer = new StringBuffer();
final StringBuilder buffer = new StringBuilder();
do {
while ((i = nextToken.indexOf('"')) >= 0) {
boolean isEscapedQuote = i > 0 && nextToken.charAt(i - 1) == '\\';
boolean isEscapedQuote = isEscapedAtPos(nextToken, i);
if (!isEscapedQuote) quotationMarks++;
buffer.append(nextToken.substring(0, isEscapedQuote ? i - 1 : i));
if (isEscapedQuote) buffer.append('"');
@@ -120,7 +120,7 @@ public class CommandLineTokenizer extends StringTokenizer {
buffer.append(nextToken);
}
if ((isEscapedWhitespace || quotationMarks % 2 == 1) && super.hasMoreTokens()) {
if ((isEscapedWhitespace || (quotationMarks & 1) == 1) && super.hasMoreTokens()) {
nextToken = super.nextToken();
} else {
nextToken = null;
@@ -129,4 +129,14 @@ public class CommandLineTokenizer extends StringTokenizer {
return buffer.toString();
}
private static boolean isEscapedAtPos(String token, int pos) {
int escapeCount = 0;
--pos;
while (pos >= 0 && token.charAt(pos) == '\\') {
++escapeCount;
--pos;
}
return (escapeCount & 1) == 1;
}
}
@@ -1977,11 +1977,19 @@ public class StringUtil extends StringUtilRt {
@Contract(pure = true)
public static String unescapeSlashes(@NotNull final String str) {
final StringBuilder buf = new StringBuilder(str.length());
unescapeSlashes(buf, str);
unescapeChar(buf, str, '/');
return buf.toString();
}
private static void unescapeSlashes(@NotNull StringBuilder buf, @NotNull String str) {
@NotNull
@Contract(pure = true)
public static String unescapeBackSlashes(@NotNull final String str) {
final StringBuilder buf = new StringBuilder(str.length());
unescapeChar(buf, str, '\\');
return buf.toString();
}
private static void unescapeChar(@NotNull StringBuilder buf, @NotNull String str, char unescapeChar) {
final int length = str.length();
final int last = length - 1;
for (int i = 0; i < length; i++) {
@@ -1989,7 +1997,7 @@ public class StringUtil extends StringUtilRt {
if (ch == '\\' && i != last) {
i++;
ch = str.charAt(i);
if (ch != '/') buf.append('\\');
if (ch != unescapeChar) buf.append('\\');
}
buf.append(ch);
@@ -24,8 +24,10 @@ public class CommandLineTokenizerTest extends TestCase {
assertTokens("a\" b\"", "a b");
assertTokens("\"a b", "a b");
assertTokens("a b\"", "a", "b");
assertTokens("a b\\\"", "a", "b\"");
assertTokens("a b\" c", "a", "b c");
assertTokens("\"a b\" c \"d e\"", "a b", "c", "d e");
assertTokens("\"-Dquote=\\\\\"", "-Dquote=\\\\");
}
public void testEscape() throws Exception {
@@ -43,6 +45,11 @@ public class CommandLineTokenizerTest extends TestCase {
assertTokens("\\\"a b\\\"", "\"a", "b\"");
assertTokens("\\\"a\\ b\\\"", true, "\"a b\"");
assertTokens("\\\"a\\ b\\\"", false, "\"a\\", "b\"");
// Check tail \" as Java does (most compatible way to go: doubling the tail backslash), see comment in
// http://cr.openjdk.java.net/~uta/openjdk-webrevs/JDK-8016046/webrev.01/src/windows/classes/java/lang/ProcessImpl.java.frames.html
// line L188/R199
assertTokens("\"-lib=c:\\My Lib\\\\\" \"-include=c:\\My Include\\\\\"", true, "-lib=c:\\My Lib\\\\", "-include=c:\\My Include\\\\");
}
private static void assertTokens(String cmd, String... tokens) {