### Eclipse Workspace Patch 1.0 #P org.eclipse.cdt.make.core Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.cdt-build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java,v retrieving revision 1.12 diff -u -r1.12 GCCPerFileBOPConsoleParser.java --- src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java 25 Aug 2006 19:53:26 -0000 1.12 +++ src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java 4 Feb 2007 23:28:33 -0000 @@ -75,17 +75,24 @@ if (compilerInvocationIndex == -1) return rc; - // expecting that compiler invocation is the first token in the line - String[] split = line.split("\\s+"); //$NON-NLS-1$ - String command = split[0]; - // verify that it is compiler invocation - int cii2 = -1; - for (int cii = 0; cii < compilerInvocation.length; ++cii) { - cii2 = command.indexOf(compilerInvocation[cii]); - if (cii2 != -1) + // split and unquote all segments; supports build command such as + // sh -c 'gcc -g -O0 -I"includemath" -I "include abc" -Iincludeprint -c impl/testmath.c' + ArrayList split = splitLine(line, compilerInvocationIndex); + + // get the position of the compiler command in the build command + for (compilerInvocationIndex=0; compilerInvocationIndex= 0) + break; + } + if (cii2 >= 0) break; - } - if (cii2 == -1) { + } + if (compilerInvocationIndex >= split.size()) { TraceUtil.outputTrace("Error identifying compiler command", line, TraceUtil.EOL); //$NON-NLS-1$ return rc; } @@ -93,13 +100,14 @@ int extensionsIndex = -1; boolean found = false; String filePath = null; - for (int i = 1; i < split.length; ++i) { - int k = split[i].lastIndexOf('.'); - if (k != -1 && (split[i].length() - k < 5)) { - String fileExtension = split[i].substring(k); + for (int i = compilerInvocationIndex+1; i < split.size(); ++i) { + String segment = (String)split.get(i); + int k = segment.lastIndexOf('.'); + if (k != -1 && (segment.length() - k < 5)) { + String fileExtension = segment.substring(k); extensionsIndex = FILE_EXTENSIONS_LIST.indexOf(fileExtension); if (extensionsIndex != -1) { - filePath = split[i]; + filePath = segment; found = true; break; } @@ -128,25 +136,23 @@ String shortFileName = pFilePath.removeFileExtension().lastSegment(); // generalize occurances of the file name - StringBuffer genericLine = new StringBuffer(); - for (int i = 0; i < split.length; i++) { - String token = split[i]; - if (token.equals("-include") || token.equals("-imacros")) { //$NON-NLS-1$ //$NON-NLS-2$ + for (int i = 0; i < split.size(); i++) { + String token = (String)split.get(i); + if (token.equals("-include")) { //$NON-NLS-1$ + ++i; + } + else if (token.equals("-imacros")) { //$NON-NLS-1$ ++i; - genericLine.append(token); - genericLine.append(' '); } else if (token.equals(filePath)) { - split[i] = "LONG_NAME"; //$NON-NLS-1$ + split.set(i, "LONG_NAME"); //$NON-NLS-1$ } else if (token.startsWith(shortFileName)) { - split[i] = token.replaceFirst(shortFileName, "SHORT_NAME"); //$NON-NLS-1$ + split.set(i, token.replaceFirst(shortFileName, "SHORT_NAME")); //$NON-NLS-1$ } - genericLine.append(split[i]); - genericLine.append(' '); } - CCommandDSC cmd = fUtil.getNewCCommandDSC(genericLine.toString(), extensionsIndex > 0); + CCommandDSC cmd = fUtil.getNewCCommandDSC((String[])split.toArray(new String[split.size()]), extensionsIndex > 0); IPath baseDirectory = fUtil.getBaseDirectory(); if (baseDirectory.isPrefixOf(pFilePath)) { List cmdList = new ArrayList(); @@ -174,4 +180,100 @@ return rc; } + /** + * Splits and unquotes all compiler command segments; supports build command such as + * sh -c 'gcc -g -O0 -I"includemath" -I "include abc" -Iincludeprint -c impl/testmath.c' + */ + private ArrayList splitLine(String line, int compilerInvocationIndex) { + ArrayList split = new ArrayList(); + boolean bSingleQuotes = false; + boolean bIgnoreSingleQuotes = false; + boolean bDoubleQuotes = false; + boolean bIgnoreDoubleQuotes = false; + char[] chars = line.toCharArray(); + int charPos = 0; + int length = line.length(); + + // eat whitespace + while (charPos < length) { + char ch = chars[charPos]; + if (!Character.isWhitespace(ch)) { + break; + } + charPos++; + } + // read token + while (charPos= 0) { + endPos = charPos; // end of a token + } + } + else if (ch == '"') { + // ignore quotes before the actual compiler command (the command itself including its options + // could be within quotes--in this case we nevertheless want to split the compiler command into segments) + if (charPos <= compilerInvocationIndex) { + bIgnoreDoubleQuotes = !bIgnoreDoubleQuotes; + } + else { + if (bIgnoreDoubleQuotes) { + bIgnoreDoubleQuotes = false; + charPos = length; // quit after closed quote containing the actual compiler command + break; + } + else { + bDoubleQuotes = !bDoubleQuotes; + } + } + if (startPos >= 0) { + endPos = charPos; // end of a token + } + } + else if (Character.isWhitespace(ch)) { + if (startPos < 0 && (bSingleQuotes || bDoubleQuotes)) { + startPos = charPos; + } + else if (startPos >= 0 && !bSingleQuotes && !bDoubleQuotes) { + endPos = charPos; // end of a token + } + } + else { // a valid character, starts or continues a token + if (startPos < 0) { + startPos = charPos; + } + if (charPos == length) { + endPos = charPos; // end of token + } + } + charPos++; + // a complete token has been found + if (startPos >= 0 && endPos > startPos) { + break; + } + } + if (startPos >= 0 && endPos >= 0 && startPos >= compilerInvocationIndex) { + split.add(line.substring(startPos, endPos)); + } + } + return split; + } }