throw new CoreException(status);
}
- private static String[] parseArgumentsWindows(String args) {
+ private static String[] parseArgumentsWindows(String args, boolean split) {
// see http://msdn.microsoft.com/en-us/library/a1y7w461.aspx
List<String> result = new ArrayList<String>();
if (ch == '"') {
for (; backslashes >= 2; backslashes-= 2) {
buf.append('\\');
+ if (split) {
+ buf.append('\\');
+ }
}
if (backslashes == 1) {
if (state == DEFAULT) {
state= ARG;
}
+ if (split) {
+ buf.append('\\');
+ }
buf.append('"');
backslashes= 0;
continue;
case ARG:
if (ch == '"') {
state= IN_DOUBLE_QUOTE;
+ if (split) {
+ buf.append(ch);
+ }
} else {
state= ARG;
buf.append(ch);
*/
buf.append('"');
i++;
+ if (split) {
+ buf.append(ch);
+ }
} else if (buf.length() == 0) {
// empty string on Windows platform. Account for bug in constructor of JDK's java.lang.ProcessImpl.
result.add("\"\""); //$NON-NLS-1$
state= DEFAULT;
} else {
state= ARG;
+ if (split) {
+ buf.append(ch);
+ }
}
} else {
buf.append(ch);
return result.toArray(new String[result.size()]);
}
- private static String[] parseArgumentsImpl(String args) {
+ private static String[] parseArgumentsImpl(String args, boolean split) {
// man sh, see topic QUOTING
List<String> result = new ArrayList<String>();
case DEFAULT:
case ARG:
if (ch == '"') {
+ if (split) {
+ buf.append(ch);
+ }
state= IN_DOUBLE_QUOTE;
} else if (ch == '\'') {
+ if (split) {
+ buf.append(ch);
+ }
state= IN_SINGLE_QUOTE;
} else if (ch == '\\' && i + 1 < len) {
+ if (split) {
+ buf.append(ch);
+ }
state= ARG;
ch= args.charAt(++i);
buf.append(ch);
case IN_DOUBLE_QUOTE:
if (ch == '"') {
+ if (split) {
+ buf.append(ch);
+ }
state= ARG;
} else if (ch == '\\' && i + 1 < len &&
(args.charAt(i + 1) == '\\' || args.charAt(i + 1) == '"')) {
+ if (split) {
+ buf.append(ch);
+ }
ch= args.charAt(++i);
buf.append(ch);
} else {
case IN_SINGLE_QUOTE:
if (ch == '\'') {
+ if (split) {
+ buf.append(ch);
+ }
state= ARG;
} else {
buf.append(ch);
}
/**
- * Parses the given command line into separate arguments that can be passed to
- * <code>DebugPlugin.exec(String[], File)</code>. Embedded quotes and slashes
- * are escaped.
+ * Parses the given command line into separate arguments that can be passed
+ * to <code>DebugPlugin.exec(String[], File)</code>. Embedded quotes and
+ * backslashes are interpreted, i.e. the resulting arguments are in the form
+ * that will be passed to an invoked process.
+ * <p>
+ * The reverse operation is {@link #renderArguments(String[], int[])}.
+ * </p>
*
* @param args command line arguments as a single string
* @return individual arguments
+ * @see #renderArguments(String[], int[])
* @since 3.1
*/
public static String[] parseArguments(String args) {
}
if (Constants.OS_WIN32.equals(Platform.getOS())) {
- return parseArgumentsWindows(args);
+ return parseArgumentsWindows(args, false);
}
- return parseArgumentsImpl(args);
+ return parseArgumentsImpl(args, false);
}
/**
- * Renders the given array of strings into a single command line.
+ * Splits the given command line into separate arguments that can be
+ * concatenated with a space as joiner. Embedded quotes and backslashes are
+ * kept as is (i.e. not interpreted).
+ *
+ * @param args command line arguments as a single string
+ * @return individual arguments in original (
+ * @since 3.10
+ */
+ public static String[] splitArguments(String args) {
+ if (args == null) {
+ return new String[0];
+ }
+
+ if (Constants.OS_WIN32.equals(Platform.getOS())) {
+ return parseArgumentsWindows(args, true);
+ }
+
+ return parseArgumentsImpl(args, true);
+ }
+
+ /**
+ * Renders the given array of argument strings into a single command line.
+ * <p>
+ * If an argument contains whitespace, it it quoted. Contained quotes or
+ * backslashes will be escaped.
+ * </p>
* <p>
* If <code>segments</code> is not <code>null</code>, the array is filled
* with the offsets of the start positions of arguments 1 to
* <code>arguments.length - 1</code>, as rendered in the resulting string.
* </p>
*
- * @param arguments
- * the command line arguments
- * @param segments
- * an array of size <code>arguments.length - 1</code> or
+ * @param arguments the command line arguments
+ * @param segments an array of size <code>arguments.length - 1</code> or
* <code>null</code>
* @return the command line
+ * @see #parseArguments(String)
* @since 3.8
*/
public static String renderArguments(String[] arguments, int[] segments) {
Arrays.asList(arguments2).toString());
}
+ String[] splitArguments = DebugPlugin.splitArguments(commandLine);
+ assertEquals(expectedArgs.length, splitArguments.length);
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < splitArguments.length; i++) {
+ if (i > 0) {
+ sb.append(" "); //$NON-NLS-1$
+ }
+ sb.append(splitArguments[i]);
+ }
+ assertEquals(commandLine, sb.toString());
}
private static void runCommandLine(String commandLine, String[] arguments) throws IOException,
public void test100arg() throws Exception {
StringBuffer buf = new StringBuffer();
- for (int i = 0; i < 100; i++)
- {
+ for (int i = 0; i < 100; i++) {
buf.append("a "); //$NON-NLS-1$
}
+ buf.deleteCharAt(buf.length() - 1);
String[] args = new String[100];
Arrays.fill(args, "a"); //$NON-NLS-1$
execute(buf.toString(), args, buf.toString().trim());