/*******************************************************************************
* Copyright (c) 2008, 2009 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX Software Systems - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.utils;
import java.util.ArrayList;
import org.eclipse.osgi.service.environment.Constants;
/**
* Utilities to work with command line, parse arguments, etc.
* @noextend This class is not intended to be subclassed by clients.
* @noinstantiate This class is not intended to be instantiated by clients.
* @since 5.1
*/
public class CommandLineUtil {
public static String[] argumentsToArray(String line) {
boolean osWin;
try {
osWin = Platform.getOS().equals(Constants.OS_WIN32);
} catch (Exception e) {
osWin = false;
}
if (osWin) {
return argumentsToArrayWindowsStyle(line);
} else {
return argumentsToArrayUnixStyle(line);
}
}
/**
* Parsing arguments in a shell style.
* i.e.
* <code>
* ["a b c" d] -> [[a b c],[d]]
* [a d] -> [[a],[d]]
* ['"quoted"'] -> [["quoted"]]
* [\\ \" \a] -> [[\],["],[a]]
* ["str\\str\a"] -> [[str\str\a]]
* </code>
* @param line
* @return array of arguments, or empty array if line is null or empty
*/
public static String[] argumentsToArrayUnixStyle(String line) {
final int INITIAL = 0;
final int IN_DOUBLE_QUOTES = 1;
final int IN_DOUBLE_QUOTES_ESCAPED = 2;
final int ESCAPED = 3;
final int IN_SINGLE_QUOTES = 4;
final int IN_ARG = 5;
if (line == null) {
line = ""; //$NON-NLS-1$
}
char[] array = line.trim().toCharArray();
ArrayList<String> aList = new ArrayList<String>();
StringBuilder buffer = new StringBuilder();
int state = INITIAL;
for (int i = 0; i < array.length; i++) {
char c = array[i];
switch (state) {
case IN_ARG:
// fall through
case INITIAL:
if (Character.isWhitespace(c)) {
if (state == INITIAL) break; // ignore extra spaces
// add argument
state = INITIAL;
String arg = buffer.toString();
buffer = new StringBuilder();
aList.add(arg);
} else {
switch (c) {
case '\\':
state = ESCAPED;
break;
case '\'':
state = IN_SINGLE_QUOTES;
break;
case '\"':
state = IN_DOUBLE_QUOTES;
break;
default:
state = IN_ARG;
buffer.append(c);
break;
}
}
break;
case IN_DOUBLE_QUOTES:
switch (c) {
case '\\':
state = IN_DOUBLE_QUOTES_ESCAPED;
break;
case '\"':
state = IN_ARG;
break;
default:
buffer.append(c);
break;
}
break;
case IN_SINGLE_QUOTES:
switch (c) {
case '\'':
state = IN_ARG;
break;
default:
buffer.append(c);
break;
}
break;
case IN_DOUBLE_QUOTES_ESCAPED:
switch (c) {
case '\"':
case '\\':
buffer.append(c);
break;
case 'n':
buffer.append("\n"); //$NON-NLS-1$
break;
default:
buffer.append('\\');
buffer.append(c);
break;
}
state = IN_DOUBLE_QUOTES;
break;
case ESCAPED:
buffer.append(c);
state = IN_ARG;
break;
}
}
if (state != INITIAL) { // this allow to process empty string as an argument
aList.add(buffer.toString());
}
return aList.toArray(new String[aList.size()]);
}
/**
* Parsing arguments in a cmd style.
* i.e.
* <code>
* ["a b c" d] -> [[a b c],[d]]
* [a d] -> [[a],[d]]
* ['"quoted"'] -> [['quoted']]
* [\\ \" \a] -> [[\\],["],[\a]]
* ["str\\str\a"] -> [[str\\str\a]]
* </code>
* @param line
* @return array of arguments, or empty array if line is null or empty
*/
public static String[] argumentsToArrayWindowsStyle(String line) {
final int INITIAL = 0;
final int IN_DOUBLE_QUOTES = 1;
final int IN_DOUBLE_QUOTES_ESCAPED = 2;
final int ESCAPED = 3;
final int IN_ARG = 5;
if (line == null) {
line = ""; //$NON-NLS-1$
}
char[] array = line.trim().toCharArray();
ArrayList<String> aList = new ArrayList<String>();
StringBuilder buffer = new StringBuilder();
int state = INITIAL;
for (int i = 0; i < array.length; i++) {
char c = array[i];
switch (state) {
case IN_ARG:
// fall through
case INITIAL:
if (Character.isWhitespace(c)) {
if (state == INITIAL) break; // ignore extra spaces
// add argument
state = INITIAL;
String arg = buffer.toString();
buffer = new StringBuilder();
aList.add(arg);
} else {
switch (c) {
case '\\':
state = ESCAPED;
break;
case '\"':
state = IN_DOUBLE_QUOTES;
break;
default:
state = IN_ARG;
buffer.append(c);
break;
}
}
break;
case IN_DOUBLE_QUOTES:
switch (c) {
case '\\':
state = IN_DOUBLE_QUOTES_ESCAPED;
break;
case '\"':
state = IN_ARG;
break;
default:
buffer.append(c);
break;
}
break;
case IN_DOUBLE_QUOTES_ESCAPED:
switch (c) {
case '\"':
buffer.append(c);
break;
default:
buffer.append('\\');
buffer.append(c);
break;
}
state = IN_DOUBLE_QUOTES;
break;
case ESCAPED:
state = IN_ARG;
switch (c) {
case ' ':
case '\"':
buffer.append(c);
break;
default:
buffer.append('\\');
buffer.append(c);
break;
}
break;
}
}
if (state != INITIAL) { // this allow to process empty string as an argument
aList.add(buffer.toString());
}
return aList.toArray(new String[aList.size()]);
}
}