diff --git a/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/BaseBOPConsoleParserTests.java b/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/BaseBOPConsoleParserTests.java index 9de787e936f..054aa50f666 100644 --- a/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/BaseBOPConsoleParserTests.java +++ b/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/BaseBOPConsoleParserTests.java @@ -81,7 +81,7 @@ public abstract class BaseBOPConsoleParserTests extends BaseTestCase { } public void testParsingSymbolDefinitions_bug80271() { - fOutputParser.processLine("gcc -DMACRO1 -I ..\\inc -c ..\\source\\source.c"); // PR 80271 //$NON-NLS-1$ + fOutputParser.processLine("gcc -DMACRO1 -I ..\\inc -c ..\\perfilescdtest\\source.c"); // PR 80271 //$NON-NLS-1$ List sumSymbols = fCollector.getCollectedScannerInfo(null, ScannerInfoTypes.SYMBOL_DEFINITIONS); assertTrue(sumSymbols.contains("MACRO1")); //$NON-NLS-1$ @@ -90,14 +90,14 @@ public abstract class BaseBOPConsoleParserTests extends BaseTestCase { public void testParsingUnbalancedDoubleQuote_Bug186065() throws Exception { fOutputParser.processLine("../src/bug186065.cc:8: error: missing terminating \" character"); // PR 80271 //$NON-NLS-1$ - fOutputParser.processLine("gcc -DBUG186065_IS_FIXED"); //$NON-NLS-1$ + fOutputParser.processLine("gcc -DBUG186065_IS_FIXED test.c"); //$NON-NLS-1$ List sumSymbols = fCollector.getCollectedScannerInfo(null, ScannerInfoTypes.SYMBOL_DEFINITIONS); assertTrue(sumSymbols.contains("BUG186065_IS_FIXED")); //$NON-NLS-1$ assertTrue(sumSymbols.size() == 1); } - public void _testCompilerCommand_bug194394() throws Exception { + public void testCompilerCommand_bug194394() throws Exception { fOutputParser.processLine("/usr/bin/gcc -DA test1.c"); //$NON-NLS-1$ fOutputParser.processLine("/usr/gcc-installs/gcc -DB test2.c"); //$NON-NLS-1$ fOutputParser.processLine("/usr/gcc/gcc -DC test3.c"); //$NON-NLS-1$ diff --git a/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/GCCPerFileBOPConsoleParserTests.java b/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/GCCPerFileBOPConsoleParserTests.java index a884fb037db..af42b9eef80 100644 --- a/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/GCCPerFileBOPConsoleParserTests.java +++ b/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/GCCPerFileBOPConsoleParserTests.java @@ -55,19 +55,4 @@ public class GCCPerFileBOPConsoleParserTests extends BaseBOPConsoleParserTests { CProjectHelper.delete(fCProject); } } - - public void testParsingSymbolDefinitions() {} - public void _testParsingSymbolDefinitions() { - super.testParsingSymbolDefinitions(); - } - - public void testParsingSymbolDefinitions_bug80271() {} - public void _testParsingSymbolDefinitions_bug80271() { - super.testParsingSymbolDefinitions_bug80271(); - } - - public void testParsingUnbalancedDoubleQuote_Bug186065() {} - public void _testParsingUnbalancedDoubleQuote_Bug186065() throws Exception { - super.testParsingUnbalancedDoubleQuote_Bug186065(); - } } diff --git a/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/GCCScannerInfoConsoleParserTests.java b/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/GCCScannerInfoConsoleParserTests.java index 67554881cf1..4f5802f31db 100644 --- a/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/GCCScannerInfoConsoleParserTests.java +++ b/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/scannerdiscovery/GCCScannerInfoConsoleParserTests.java @@ -58,7 +58,7 @@ public class GCCScannerInfoConsoleParserTests extends BaseBOPConsoleParserTests fOutputParser.processLine("gcc '-I /with spaces 1' -I'/with spaces 2' -c test.c"); // dirs with spaces 1,2 //$NON-NLS-1$ fOutputParser.processLine("gcc \"-I /with spaces 3\" -I \"/with spaces 4\" -c test.c"); // dirs with spaces 3,4 //$NON-NLS-1$ fOutputParser.processLine("gcc -I /with\\ spaces\\ 5 -c test.c"); // dirs with spaces 5 //$NON-NLS-1$ - fOutputParser.processLine("gcc -I '\\\\server1\\include' '-I\\\\server2\\include' -I \"\\\\server3\\include\" -c test.c"); // UNC paths //$NON-NLS-1$ + fOutputParser.processLine("gcc -I '\\\\server1\\include' '-I\\\\server2\\include' -I \"\\\\\\\\server3\\\\include\" -c test.c"); // UNC paths //$NON-NLS-1$ fOutputParser.processLine("gcc -I //server4/include -I '//server5/include' '-I//server6/include' -c test.c"); // UNC paths //$NON-NLS-1$ fOutputParser.processLine("gcc -I \\"); //$NON-NLS-1$ fOutputParser.processLine("/multiline\\"); //$NON-NLS-1$ @@ -91,10 +91,4 @@ public class GCCScannerInfoConsoleParserTests extends BaseBOPConsoleParserTests assertTrue(sumIncludes.contains("/multiline/dir")); //$NON-NLS-1$ assertTrue(sumIncludes.size() == 24); } - - public void testCommandsWithSemicolon_bug194394() {} - public void _testCommandsWithSemicolon_bug194394() throws Exception { - super.testCommandsWithSemicolon_bug194394(); - } - } diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParser.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParser.java index f33efac755e..568df26d63d 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParser.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParser.java @@ -6,10 +6,13 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; +import java.util.ArrayList; + import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector; import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser; import org.eclipse.cdt.make.internal.core.scannerconfig.util.TraceUtil; @@ -27,6 +30,9 @@ public abstract class AbstractGCCBOPConsoleParser implements IScannerInfoConsole private static final String[] COMPILER_INVOCATION = { "gcc", "g++", "cc", "c++" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ }; + protected static final String DASHIDASH= "-I-"; //$NON-NLS-1$ + protected static final String DASHI= "-I"; //$NON-NLS-1$ + protected static final String DASHD= "-D"; //$NON-NLS-1$ private IProject project; private IScannerInfoCollector collector; @@ -34,6 +40,8 @@ public abstract class AbstractGCCBOPConsoleParser implements IScannerInfoConsole private boolean bMultiline = false; private String sMultiline = ""; //$NON-NLS-1$ + private String[] fCompilerCommands; + /** * @return Returns the project. */ @@ -50,6 +58,7 @@ public abstract class AbstractGCCBOPConsoleParser implements IScannerInfoConsole public void startup(IProject project, IScannerInfoCollector collector) { this.project = project; this.collector = collector; + fCompilerCommands= computeCompilerCommands(); } /** @@ -57,7 +66,7 @@ public abstract class AbstractGCCBOPConsoleParser implements IScannerInfoConsole * * @return String[] */ - public String[] getCompilerCommands() { + private String[] computeCompilerCommands() { if (project != null) { SCProfileInstance profileInstance = ScannerConfigProfileManager.getInstance(). getSCProfileInstance(project, ScannerConfigProfileManager.NULL_PROFILE_ID); @@ -143,7 +152,6 @@ public abstract class AbstractGCCBOPConsoleParser implements IScannerInfoConsole return num; } - protected abstract boolean processSingleLine(String line); protected abstract AbstractGCCBOPConsoleParserUtility getUtility(); /* (non-Javadoc) @@ -154,4 +162,157 @@ public abstract class AbstractGCCBOPConsoleParser implements IScannerInfoConsole getUtility().reportProblems(); } } + + /** + * Tokenizes a line into an array of commands. Commands are separated by + * ';', '&&' or '||'. Tokens are separated by whitespace unless found inside + * of quotes, back-quotes, or double quotes. + * Outside of single-, double- or back-quotes a backslash escapes white-spaces, all quotes, + * the backslash, '&' and '|'. + * A backslash used for escaping is removed. + * Quotes other than the back-quote plus '&&', '||', ';' are removed, also. + * @param line to tokenize + * @return array of commands + */ + protected String[][] tokenize(String line, boolean escapeInsideDoubleQuotes) { + ArrayList commands= new ArrayList(); + ArrayList tokens= new ArrayList(); + StringBuffer token= new StringBuffer(); + + final char[] input= line.toCharArray(); + boolean nextEscaped= false; + char currentQuote= 0; + for (int i = 0; i < input.length; i++) { + final char c = input[i]; + final boolean escaped= nextEscaped; nextEscaped= false; + + if (currentQuote != 0) { + if (c == currentQuote) { + if (escaped) { + token.append(c); + } + else { + if (c=='`') { + token.append(c); // preserve back-quotes + } + endToken(token, tokens); + currentQuote= 0; + } + } + else { + if (escapeInsideDoubleQuotes && currentQuote == '"' && c == '\\') { + nextEscaped= !escaped; + if (escaped) { + token.append(c); + } + } + else { + if (escaped) { + token.append('\\'); + } + token.append(c); + } + } + } + else { + switch(c) { + case '\\': + if (escaped) { + token.append(c); + } + else { + nextEscaped= true; + } + break; + case '\'': case '"': case '`': + if (escaped) { + token.append(c); + } + else { + if (c == '`') { + token.append(c); + } + currentQuote= c; + } + break; + case ';': + if (escaped) { + token.append(c); + } + else { + endCommand(token, tokens, commands); + } + break; + case '&': case '|': + if (escaped || i+1 >= input.length || input[i+1] != c) { + token.append(c); + } + else { + i++; + endCommand(token, tokens, commands); + } + break; + + default: + if (Character.isWhitespace(c)) { + if (escaped) { + token.append(c); + } + else { + endToken(token, tokens); + } + } + else { + if (escaped) { + token.append('\\'); // for windows put backslash back onto the token. + } + token.append(c); + } + } + } + } + endCommand(token, tokens, commands); + return (String[][]) commands.toArray(new String[commands.size()][]); + } + + private void endCommand(StringBuffer token, ArrayList tokens, ArrayList commands) { + endToken(token, tokens); + if (!tokens.isEmpty()) { + commands.add(tokens.toArray(new String[tokens.size()])); + tokens.clear(); + } + } + private void endToken(StringBuffer token, ArrayList tokens) { + if (token.length() > 0) { + tokens.add(token.toString()); + token.setLength(0); + } + } + + protected boolean processSingleLine(String line) { + boolean rc= false; + String[][] tokens= tokenize(line, true); + for (int i = 0; i < tokens.length; i++) { + String[] command = tokens[i]; + if (processCommand(command)) { + rc= true; + } + } + return rc; + } + + protected int findCompilerInvocation(String[] tokens) { + for (int i = 0; i < tokens.length; i++) { + final String token = tokens[i].toLowerCase(); + final int searchFromOffset= Math.max(token.lastIndexOf('/'), token.lastIndexOf('\\')) + 1; + for (int j=0; j < fCompilerCommands.length; j++) { + if (token.indexOf(fCompilerCommands[j], searchFromOffset) != -1) { + return i; + } + } + } + return -1; + } + + abstract protected boolean processCommand(String[] command); } diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java index aaeee5a2546..daccdacc595 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java @@ -6,9 +6,10 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Tianchao Li (tianchao.li@gmail.com) - arbitrary build directory (bug #136136) - * Gerhard Schaber (Wind River Systems) - bug 187910 + * IBM - Initial API and implementation + * Tianchao Li (tianchao.li@gmail.com) - arbitrary build directory (bug #136136) + * Gerhard Schaber (Wind River Systems) - bug 187910 + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; @@ -39,7 +40,6 @@ public class GCCPerFileBOPConsoleParser extends AbstractGCCBOPConsoleParser { }; private final static List FILE_EXTENSIONS_LIST = Arrays.asList(FILE_EXTENSIONS); - private String[] compilerInvocation; private GCCPerFileBOPConsoleParserUtility fUtil; /* (non-Javadoc) @@ -49,9 +49,6 @@ public class GCCPerFileBOPConsoleParser extends AbstractGCCBOPConsoleParser { fUtil = (project != null && workingDirectory != null && markerGenerator != null) ? new GCCPerFileBOPConsoleParserUtility(project, workingDirectory, markerGenerator) : null; super.startup(project, collector); - - // check additional compiler commands from extension point manifest - compilerInvocation = getCompilerCommands(); } /* (non-Javadoc) @@ -64,76 +61,46 @@ public class GCCPerFileBOPConsoleParser extends AbstractGCCBOPConsoleParser { /* (non-Javadoc) * @see org.eclipse.cdt.make.internal.core.scannerconfig.gnu.AbstractGCCBOPConsoleParser#processSingleLine(java.lang.String) */ - protected boolean processSingleLine(String line) { - boolean rc = false; + protected boolean processCommand(String[] tokens) { // GCC C/C++ compiler invocation - int compilerInvocationIndex = -1; - for (int cii = 0; cii < compilerInvocation.length; ++cii) { - compilerInvocationIndex = line.indexOf(compilerInvocation[cii]); - if (compilerInvocationIndex != -1) - break; + int compilerInvocationIndex= findCompilerInvocation(tokens); + if (compilerInvocationIndex < 0) { + return false; } - if (compilerInvocationIndex == -1) - return rc; - // 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 (compilerInvocationIndex >= split.size()) { - TraceUtil.outputTrace("Error identifying compiler command", line, TraceUtil.EOL); //$NON-NLS-1$ - return rc; - } // find a file name int extensionsIndex = -1; boolean found = false; String filePath = null; - 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); + for (int i = compilerInvocationIndex+1; i < tokens.length; i++) { + String token= tokens[i]; + int k = token.lastIndexOf('.'); + if (k != -1 && (token.length() - k < 5)) { + String fileExtension = token.substring(k); extensionsIndex = FILE_EXTENSIONS_LIST.indexOf(fileExtension); if (extensionsIndex != -1) { - filePath = segment; + filePath = token; found = true; break; } } } -// for (int j = 0; j < FILE_EXTENSIONS.length; ++j) { -// if (split[i].endsWith(FILE_EXTENSIONS[j])) { -// filePath = split[i]; -// extensionsIndex = j; -// found = true; -// break; -// } -// } -// if (found) break; if (!found) { - TraceUtil.outputTrace("Error identifying file name :1", line, TraceUtil.EOL); //$NON-NLS-1$ - return rc; + TraceUtil.outputTrace("Error identifying file name :1", tokens, TraceUtil.EOL); //$NON-NLS-1$ + return true; } // sanity check if (filePath.indexOf(FILE_EXTENSIONS[extensionsIndex]) == -1) { - TraceUtil.outputTrace("Error identifying file name :2", line, TraceUtil.EOL); //$NON-NLS-1$ - return rc; + TraceUtil.outputTrace("Error identifying file name :2", tokens, TraceUtil.EOL); //$NON-NLS-1$ + return true; } if (fUtil != null) { IPath pFilePath = fUtil.getAbsolutePath(filePath); String shortFileName = pFilePath.removeFileExtension().lastSegment(); - // generalize occurances of the file name - for (int i = 0; i < split.size(); i++) { - String token = (String)split.get(i); + // generalize occurrences of the file name + for (int i = compilerInvocationIndex+1; i < tokens.length; i++) { + String token = tokens[i]; if (token.equals("-include")) { //$NON-NLS-1$ ++i; } @@ -141,14 +108,14 @@ public class GCCPerFileBOPConsoleParser extends AbstractGCCBOPConsoleParser { ++i; } else if (token.equals(filePath)) { - split.set(i, "LONG_NAME"); //$NON-NLS-1$ + tokens[i]= "LONG_NAME"; //$NON-NLS-1$ } else if (token.startsWith(shortFileName)) { - split.set(i, token.replaceFirst(shortFileName, "SHORT_NAME")); //$NON-NLS-1$ + tokens[i]= token.replaceFirst(shortFileName, "SHORT_NAME"); //$NON-NLS-1$ } } - CCommandDSC cmd = fUtil.getNewCCommandDSC((String[])split.toArray(new String[split.size()]), extensionsIndex > 0); + CCommandDSC cmd = fUtil.getNewCCommandDSC(tokens, extensionsIndex > 0); IPath baseDirectory = fUtil.getBaseDirectory(); if (baseDirectory.isPrefixOf(pFilePath)) { List cmdList = new ArrayList(); @@ -157,7 +124,7 @@ public class GCCPerFileBOPConsoleParser extends AbstractGCCBOPConsoleParser { sc.put(ScannerInfoTypes.COMPILER_COMMAND, cmdList); IPath relPath = pFilePath.removeFirstSegments(baseDirectory.segmentCount()); - //Note: We add the scannerconfig even if the resource doesnt actually + //Note: We add the scanner-config even if the resource doesn't actually //exist below this project (which may happen when reading existing //build logs, because resources can be created as part of the build //and may not exist at the time of analyzing the config but re-built @@ -166,161 +133,13 @@ public class GCCPerFileBOPConsoleParser extends AbstractGCCBOPConsoleParser { IFile file = getProject().getFile(relPath); getCollector().contributeToScannerConfig(file, sc); } else { - //TODO limiting to pathes below this project means not being + //TODO limiting to paths below this project means not being //able to work with linked resources. Linked resources could //be checked through IWorkspaceRoot.findFilesForLocation(). - TraceUtil.outputError("Build command for file outside project: "+pFilePath.toString(), line); //$NON-NLS-1$ + TraceUtil.outputError("Build command for file outside project: "+pFilePath.toString(), tokens); //$NON-NLS-1$ } // fUtil.addGenericCommandForFile2(longFileName, genericLine); } - return rc; - } - - private int lastIndexOfCompilerCommand(String command) { - int cii2 = -1; - for (int cii = 0; cii < compilerInvocation.length; ++cii) { - cii2 = command.lastIndexOf(compilerInvocation[cii]); - if (cii2 >= 0) { - break; - } - } - return cii2; - } - - /** - * 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(); - boolean quit = false; - boolean acceptExtraSingleQuote = false; - boolean acceptExtraDoubleQuote = false; - - // 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 - } - quit = true; // quit after closed quote containing the actual compiler command - } - else { - bSingleQuotes = !bSingleQuotes; - } - } -// do split token here: allow -DMYKEY='MYVALUE' or-DMYKEY=\'MYVALUE\' - if (startPos >= 0) { - char prevch = charPos > 0 ? chars[charPos-1] : '\0'; - if (acceptExtraSingleQuote) { - acceptExtraSingleQuote = false; - } - else if (prevch != '=' && prevch != '\\') { - endPos = charPos; // end of a token - } - else { - acceptExtraSingleQuote = true; - } - } - } - 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; - if (startPos >= 0) { - endPos = charPos; // end of a token - } - quit = true; // quit after closed quote containing the actual compiler command - } - else { - bDoubleQuotes = !bDoubleQuotes; - } - } -// do split token here: allow -DMYKEY="MYVALUE" or-DMYKEY=\"MYVALUE\" - if (startPos >= 0) { - char prevch = charPos > 0 ? chars[charPos-1] : '\0'; - if (acceptExtraDoubleQuote) { - acceptExtraDoubleQuote = false; - } - else if (prevch != '=' && prevch != '\\') { - endPos = charPos; // end of a token - } - else { - acceptExtraDoubleQuote = true; - } - } - } - else if (Character.isWhitespace(ch) || 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-1) { - endPos = charPos+1; // end of token - } - } - charPos++; - // a complete token has been found - if (startPos >= 0 && endPos > startPos) { - break; - } - } - if (startPos >= 0 && endPos >= 0) { - String cmdFragment = line.substring(startPos, endPos); - if (startPos >= compilerInvocationIndex) { // the compiler name or one of its options - split.add(cmdFragment); - } - else if (endPos > compilerInvocationIndex) { - // compiler name is found within another command fragment--we have to check, whether this - // is a valid compiler invocation (e.g., C:/Programs/gcc/gcc.exe) or only a part - // of a command that contains by chance the compiler name (e.g., cat testgccsettings.txt) - int idx = lastIndexOfCompilerCommand(cmdFragment); - if (idx == 0 || - (idx > 0 && (cmdFragment.charAt(idx-1) == '\\' || cmdFragment.charAt(idx-1) == '/'))) { - split.add(cmdFragment); - } - } - } - } - return split; + return true; } } diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParserUtility.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParserUtility.java index cac04b08513..d1dafb488b1 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParserUtility.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParserUtility.java @@ -6,9 +6,10 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Martin Oberhuber (Wind River Systems) - bug 155096 - * Gerhard Schaber (Wind River Systems) + * IBM - Initial API and implementation + * Martin Oberhuber (Wind River Systems) - bug 155096 + * Gerhard Schaber (Wind River Systems) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; @@ -177,9 +178,8 @@ public class GCCPerFileBOPConsoleParserUtility extends AbstractGCCBOPConsolePars else { // ex. -I /dir // take a next token - ++i; - if (i < tokens.length && !tokens[i].startsWith("-")) { //$NON-NLS-1$ - option = tokens[i]; + if (i+1 < tokens.length && !tokens[i+1].startsWith("-")) { //$NON-NLS-1$ + option = tokens[++i]; } else break; } diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoConsoleParser.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoConsoleParser.java index 636106a1401..86487fa0e3f 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoConsoleParser.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoConsoleParser.java @@ -6,16 +6,15 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Martin Oberhuber (Wind River Systems) - bug 155096 - * Sergey Prigogin (Google) + * IBM - Initial API and implementation + * Martin Oberhuber (Wind River Systems) - bug 155096 + * Sergey Prigogin (Google) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; @@ -35,13 +34,8 @@ import org.eclipse.core.runtime.Path; * @author vhirsl */ public class GCCScannerInfoConsoleParser extends AbstractGCCBOPConsoleParser { - private final static String SINGLE_QUOTE_STRING = "\'"; //$NON-NLS-1$ - private final static String DOUBLE_QUOTE_STRING = "\""; //$NON-NLS-1$ - private final static char[] matchingChars = {'`', '\'', '\"'}; - - private String[] compilerInvocation; - private ScannerInfoConsoleParserUtility fUtil = null; + private ScannerInfoConsoleParserUtility fUtil = null; /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser#startup(org.eclipse.core.resources.IProject, org.eclipse.core.runtime.IPath, org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector, org.eclipse.cdt.core.IMarkerGenerator) @@ -50,9 +44,6 @@ public class GCCScannerInfoConsoleParser extends AbstractGCCBOPConsoleParser { fUtil = (project != null && workingDirectory != null && markerGenerator != null) ? new ScannerInfoConsoleParserUtility(project, workingDirectory, markerGenerator) : null; super.startup(project, collector); - - // check additional compiler commands from extension point manifest - compilerInvocation = getCompilerCommands(); } /* (non-Javadoc) @@ -62,290 +53,144 @@ public class GCCScannerInfoConsoleParser extends AbstractGCCBOPConsoleParser { return fUtil; } - /* (non-Javadoc) - * @see org.eclipse.cdt.make.internal.core.scannerconfig.gnu.AbstractGCCBOPConsoleParser#processSingleLine(java.lang.String) - */ - protected boolean processSingleLine(String line) { - boolean rc = false; - // Known patterns: - // (a) gcc|g++ ... -Dxxx -Iyyy ... - List allTokens = tokenize(line); -// ArrayList allTokens = new ArrayList(Arrays.asList(line.split("\\s+")));//$NON-NLS-1$ - if (allTokens.size() <= 1) - return false; + protected boolean processCommand(String[] tokens) { + int compilerInvocationIdx= findCompilerInvocation(tokens); + if (compilerInvocationIdx<0) { + return false; + } - boolean found = false; - Iterator I = allTokens.iterator(); - String token; - for (int ti = 0; ti < 2; ++ti) { - token = ((String) I.next()).toLowerCase(); - for (int i = 0; i < compilerInvocation.length; i++) { - if (token.indexOf(compilerInvocation[i]) != -1) { - found = true; - break; - } - } - if (found) - break; - } - - if (found) { - // Recognized gcc or g++ compiler invocation - List includes = new ArrayList(); - List symbols = new ArrayList(); - List targetSpecificOptions = new ArrayList(); + // Recognized gcc or g++ compiler invocation + List includes = new ArrayList(); + List symbols = new ArrayList(); + List targetSpecificOptions = new ArrayList(); - rc = true; - String fileName = null; - // discover all -I options - parseLineForIncludePaths(line, includes); - // discover all -D options - parseLineForSymbolDefinitions(line, symbols); - - while (I.hasNext()) { - token = (String) I.next(); - if (token.startsWith("-m") || //$NON-NLS-1$ - token.equals("-ansi") || //$NON-NLS-1$ - token.equals("-nostdinc") || //$NON-NLS-1$ - token.equals("-posix") || //$NON-NLS-1$ - token.equals("-pthread") || //$NON-NLS-1$ - token.startsWith("-O") || //$NON-NLS-1$ - token.equals("-fno-inline") || //$NON-NLS-1$ - token.startsWith("-finline") || //$NON-NLS-1$ - token.equals("-fno-exceptions") || //$NON-NLS-1$ - token.equals("-fexceptions") || //$NON-NLS-1$ - token.equals("-fshort-wchar") || //$NON-NLS-1$ - token.equals("-fshort-double") || //$NON-NLS-1$ - token.equals("-fno-signed-char") || //$NON-NLS-1$ - token.equals("-fsigned-char") || //$NON-NLS-1$ - token.startsWith("-fabi-version=") //$NON-NLS-1$ - ) { - if (!targetSpecificOptions.contains(token)) - targetSpecificOptions.add(token); + String fileName = null; + for (int j= compilerInvocationIdx+1; j < tokens.length; j++) { + String token = tokens[j]; + if (token.equals(DASHIDASH)) { + } + else if (token.startsWith(DASHI)) { + String candidate= null; + if (token.length() > 2) { + candidate= token.substring(2).trim(); } - else if (fileName == null) { - String possibleFileName = token.toLowerCase(); - if (possibleFileName.length() >= 5 && // Two quotes plus 3 characters for file name. - (possibleFileName.startsWith(DOUBLE_QUOTE_STRING) && - possibleFileName.endsWith(DOUBLE_QUOTE_STRING)) || - (possibleFileName.startsWith(SINGLE_QUOTE_STRING) && - possibleFileName.endsWith(SINGLE_QUOTE_STRING))) { - possibleFileName = possibleFileName.substring(1, possibleFileName.length()-1).trim(); - } - if (possibleFileName.endsWith(".c") || //$NON-NLS-1$ - possibleFileName.endsWith(".cpp") || //$NON-NLS-1$ - possibleFileName.endsWith(".cc") || //$NON-NLS-1$ - possibleFileName.endsWith(".cxx") || //$NON-NLS-1$ - possibleFileName.endsWith(".C") || //$NON-NLS-1$ - possibleFileName.endsWith(".CPP") || //$NON-NLS-1$ - possibleFileName.endsWith(".CC") || //$NON-NLS-1$ - possibleFileName.endsWith(".CXX") || //$NON-NLS-1$ - possibleFileName.endsWith(".c++")) { //$NON-NLS-1$ - - fileName = token; - } - } - } - - if (fileName != null && fileName.startsWith("/cygdrive/")) { //$NON-NLS-1$ - fileName= AbstractGCCBOPConsoleParserUtility.convertCygpath(new Path(fileName)).toOSString(); - } - - IProject project = getProject(); - IFile file = null; - List translatedIncludes = includes; - if (includes.size() > 0) { - if (fileName != null) { - if (fUtil != null) { - file = fUtil.findFile(fileName); - if (file != null) { - project = file.getProject(); - translatedIncludes = fUtil.translateRelativePaths(file, fileName, includes); - } - } - } - else { - final String error = MakeMessages.getString("ConsoleParser.Filename_Missing_Error_Message"); //$NON-NLS-1$ - TraceUtil.outputError(error, line); - if (fUtil != null) { - fUtil.generateMarker(getProject(), -1, error + line, IMarkerGenerator.SEVERITY_WARNING, null); - } - } - if (file == null && fUtil != null) { // real world case - // remove include paths since there was no chance to translate them - translatedIncludes.clear(); - } - } - // Contribute discovered includes and symbols to the ScannerInfoCollector - if (translatedIncludes.size() > 0 || symbols.size() > 0) { - Map scannerInfo = new HashMap(); - scannerInfo.put(ScannerInfoTypes.INCLUDE_PATHS, translatedIncludes); - scannerInfo.put(ScannerInfoTypes.SYMBOL_DEFINITIONS, symbols); - scannerInfo.put(ScannerInfoTypes.TARGET_SPECIFIC_OPTION, targetSpecificOptions); - getCollector().contributeToScannerConfig(project, scannerInfo); - - TraceUtil.outputTrace("Discovered scanner info for file \'" + fileName + '\'', //$NON-NLS-1$ - "Include paths", includes, translatedIncludes, "Defined symbols", symbols); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - return rc; - } - - /** - * @param line - * @return list of tokens - */ - private List tokenize(String line) { - List rv = new ArrayList(2); - // find special characters that need to be matched: `, ' and " - // First Matching Chararcter - int prevFmc = line.length(); - int emc = -1; - char matchingChar = 0; - for (int i = 0; i < matchingChars.length; ++i) { - char ch = matchingChars[i]; - int fmc = line.indexOf(ch); - if (fmc > -1 && fmc < prevFmc) { - emc = line.indexOf(ch, fmc+1); - if (emc > fmc) { - matchingChar = ch; - prevFmc = fmc; - } - } - } - if (matchingChar != 0) { // found matched chars - String prefix = line.substring(0, prevFmc).trim(); - rv.addAll(Arrays.asList(prefix.split("\\s+")));//$NON-NLS-1$ - - rv.add(line.substring(prevFmc, emc+1)); - - // recursion - rv.addAll(tokenize(line.substring(emc+1).trim())); - } - else { - rv.addAll(Arrays.asList(line.split("\\s+")));//$NON-NLS-1$ - } - return rv; - } - - /** - * @param line - * @param includes - */ - private void parseLineForIncludePaths(String line, List includes) { - final String fDashI = "-I"; //$NON-NLS-1$ - int prevIndex = 0; - for (int index = line.indexOf(fDashI, prevIndex); index != -1; - prevIndex = index+2, index = line.indexOf(fDashI, prevIndex)) { - String delimiter = "\\s+"; //$NON-NLS-1$ - if (line.charAt(index-1) == '\'' || line.charAt(index-1) == '\"') { - // look for only one more ' or " - delimiter = String.valueOf(line.charAt(index-1)); - } - String postfix = line.substring(index+2).trim(); - if (postfix.charAt(0) == '-') { // empty -I - continue; - } - if (postfix.startsWith(SINGLE_QUOTE_STRING) || postfix.startsWith(DOUBLE_QUOTE_STRING)) { - delimiter = postfix.substring(0, 1); - } - String[] tokens = postfix.split(delimiter); - int tokIndex = (tokens.length > 1 && tokens[0].length() == 0) ? 1 : 0; - String iPath = tokens[tokIndex]; - String temp = iPath; - // check for '\ ' - for (++tokIndex; (temp.endsWith("\\") && tokIndex < tokens.length && //$NON-NLS-1$ - tokens[tokIndex].length() > 0 && !tokens[tokIndex].startsWith("-")); //$NON-NLS-1$ - ++tokIndex) { - int beg = postfix.indexOf(temp)+temp.length(); - int end = postfix.indexOf(tokens[tokIndex])+tokens[tokIndex].length(); - iPath = iPath.substring(0, iPath.length()-1) + postfix.substring(beg, end); - temp += postfix.substring(beg, end); - } - String nPath = iPath; - if (fUtil != null) { - nPath = fUtil.normalizePath(iPath); - } - if (!includes.contains(nPath)) { - includes.add(nPath); - } - } - } - - /** - * @param line - * @param symbols - */ - private void parseLineForSymbolDefinitions(String line, List symbols) { - final String fDashD = "-D"; //$NON-NLS-1$ - int prevIndex = 0; - String delimiter = null; - String splitRegex = "\\s+"; //$NON-NLS-1$ - for (int index = line.indexOf(fDashD, prevIndex); index != -1; - prevIndex = index+2, index = line.indexOf(fDashD, prevIndex)) { - int nDelimiterSymbols = 2; - String postfix = line.substring(index+2).trim(); - if (postfix.charAt(0) == '-') { // empty -D - continue; - } - if (line.charAt(index-1) == '\'' || line.charAt(index-1) == '\"') { - // look for only one more ' or " - delimiter = String.valueOf(line.charAt(index-1)); - nDelimiterSymbols = 1; - } - else { - String[] tokens = postfix.split(splitRegex, 2); - if (tokens.length > 0 && tokens[0].length() > 0) { - int sQuoteIndex = tokens[0].indexOf(SINGLE_QUOTE_STRING); - int dQuoteIndex = tokens[0].indexOf(DOUBLE_QUOTE_STRING); - if (sQuoteIndex == -1 && dQuoteIndex == -1) { - // simple case, no quotes - if (!symbols.contains(tokens[0])) { - symbols.add(tokens[0]); - } - continue; + else if (j+1 < tokens.length) { + candidate= tokens[j+1]; + if (candidate.startsWith("-")) { //$NON-NLS-1$ + candidate= null; } else { - delimiter = (sQuoteIndex != -1 && (dQuoteIndex == -1 || sQuoteIndex < dQuoteIndex)) ? SINGLE_QUOTE_STRING : DOUBLE_QUOTE_STRING; + j++; } } - else - continue; - } - - // find next matching delimiter - int nextDelimiterIndex = -1; - int prevDelimiterIndex = -1; - do { - nextDelimiterIndex = postfix.indexOf(delimiter, nextDelimiterIndex+1); - if (nextDelimiterIndex == 0 || (nextDelimiterIndex > 0 && postfix.charAt(nextDelimiterIndex-1) != '\\')) { - --nDelimiterSymbols; - if (nDelimiterSymbols > 0) { - prevDelimiterIndex = nextDelimiterIndex; + if (candidate != null && candidate.length() > 0) { + if (fUtil != null) { + candidate= fUtil.normalizePath(candidate); + } + if (!includes.contains(candidate)) { + includes.add(candidate); } } - } - while (nDelimiterSymbols > 0 && nextDelimiterIndex != -1); - if (nDelimiterSymbols > 0) - continue; // non matching delimiter + } + else if (token.startsWith(DASHD)) { + String candidate= null; + if (token.length() > 2) { + candidate= token.substring(2).trim(); + } + else if (j+1 < tokens.length) { + candidate= tokens[j+1]; + if (candidate.startsWith("-")) { //$NON-NLS-1$ + candidate= null; + } + else { + j++; + } + } + if (candidate != null && candidate.length() > 0) { + if (!symbols.contains(candidate)) { + symbols.add(candidate); + } + } + } + else if (token.startsWith("-m") || //$NON-NLS-1$ + token.equals("-ansi") || //$NON-NLS-1$ + token.equals("-nostdinc") || //$NON-NLS-1$ + token.equals("-posix") || //$NON-NLS-1$ + token.equals("-pthread") || //$NON-NLS-1$ + token.startsWith("-O") || //$NON-NLS-1$ + token.equals("-fno-inline") || //$NON-NLS-1$ + token.startsWith("-finline") || //$NON-NLS-1$ + token.equals("-fno-exceptions") || //$NON-NLS-1$ + token.equals("-fexceptions") || //$NON-NLS-1$ + token.equals("-fshort-wchar") || //$NON-NLS-1$ + token.equals("-fshort-double") || //$NON-NLS-1$ + token.equals("-fno-signed-char") || //$NON-NLS-1$ + token.equals("-fsigned-char") || //$NON-NLS-1$ + token.startsWith("-fabi-version=")) { //$NON-NLS-1$ + if (!targetSpecificOptions.contains(token)) + targetSpecificOptions.add(token); + } + else if (fileName == null) { + String possibleFileName = token.toLowerCase(); + if (possibleFileName.endsWith(".c") || //$NON-NLS-1$ + possibleFileName.endsWith(".cpp") || //$NON-NLS-1$ + possibleFileName.endsWith(".cc") || //$NON-NLS-1$ + possibleFileName.endsWith(".cxx") || //$NON-NLS-1$ + possibleFileName.endsWith(".C") || //$NON-NLS-1$ + possibleFileName.endsWith(".CPP") || //$NON-NLS-1$ + possibleFileName.endsWith(".CC") || //$NON-NLS-1$ + possibleFileName.endsWith(".CXX") || //$NON-NLS-1$ + possibleFileName.endsWith(".c++")) { //$NON-NLS-1$ + fileName = token; + } + } + } - // take everything up to the last delimiter - boolean bStartsWithDelimiter = postfix.startsWith(delimiter); - String symbol = postfix.substring(bStartsWithDelimiter ? 1 : 0, nextDelimiterIndex); - if (!bStartsWithDelimiter) { - // there is still a delimiter to be removed - if (prevDelimiterIndex != -1) { - symbol = symbol.substring(0, prevDelimiterIndex) + symbol.substring(prevDelimiterIndex+1); + if (fileName != null && fileName.startsWith("/cygdrive/")) { //$NON-NLS-1$ + fileName= AbstractGCCBOPConsoleParserUtility.convertCygpath(new Path(fileName)).toOSString(); + } + + IProject project = getProject(); + IFile file = null; + List translatedIncludes = includes; + if (includes.size() > 0) { + if (fileName != null) { + if (fUtil != null) { + file = fUtil.findFile(fileName); + if (file != null) { + project = file.getProject(); + translatedIncludes = fUtil.translateRelativePaths(file, fileName, includes); + } + } + } + else { + StringBuffer line= new StringBuffer(); + for (int j = 0; j < tokens.length; j++) { + line.append(tokens[j]); + line.append(' '); } - } - // transform '\"' into '"' - if (delimiter.equals(DOUBLE_QUOTE_STRING)) { - symbol = symbol.replaceAll("\\\\\"", DOUBLE_QUOTE_STRING); //$NON-NLS-1$ - } - if (!symbols.contains(symbol)) { - symbols.add(symbol); - } - } + final String error = MakeMessages.getString("ConsoleParser.Filename_Missing_Error_Message"); //$NON-NLS-1$ + TraceUtil.outputError(error, line.toString()); + if (fUtil != null) { + fUtil.generateMarker(getProject(), -1, error + line.toString(), IMarkerGenerator.SEVERITY_WARNING, null); + } + } + if (file == null && fUtil != null) { // real world case + // remove include paths since there was no chance to translate them + translatedIncludes.clear(); + } + } + // Contribute discovered includes and symbols to the ScannerInfoCollector + if (translatedIncludes.size() > 0 || symbols.size() > 0) { + Map scannerInfo = new HashMap(); + scannerInfo.put(ScannerInfoTypes.INCLUDE_PATHS, translatedIncludes); + scannerInfo.put(ScannerInfoTypes.SYMBOL_DEFINITIONS, symbols); + scannerInfo.put(ScannerInfoTypes.TARGET_SPECIFIC_OPTION, targetSpecificOptions); + getCollector().contributeToScannerConfig(project, scannerInfo); + + TraceUtil.outputTrace("Discovered scanner info for file \'" + fileName + '\'', //$NON-NLS-1$ + "Include paths", includes, translatedIncludes, "Defined symbols", symbols); //$NON-NLS-1$ //$NON-NLS-2$ + } + return true; } - } diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CCommandDSC.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CCommandDSC.java index 105b5f00001..ccbf1c80043 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CCommandDSC.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CCommandDSC.java @@ -6,9 +6,9 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Markus Schorn (Wind River Systems) - * Gerhard Schaber (Wind River Systems) + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) + * Gerhard Schaber (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig.util; @@ -131,7 +131,7 @@ public class CCommandDSC { * @param quoteIncludePaths whether or not paths for includes must be put inside double quotes. * @return the command line to run the scanner discovery. */ - public String getSCDRunnableCommand(boolean quoteIncludePaths) { + public String getSCDRunnableCommand(boolean quoteIncludePaths, boolean quoteDefines) { String commandAsString = new String(); for (Iterator i = compilerCommand.iterator(); i.hasNext(); ) { KVStringPair optionPair = (KVStringPair)i.next(); @@ -152,6 +152,15 @@ public class CCommandDSC { value= "\"" + value + "\""; //$NON-NLS-1$ //$NON-NLS-2$ } } + else if (quoteDefines && optionPair.getKey().equals(SCDOptionsEnum.DEFINE.toString())) { + if (value.indexOf('\'') == -1) { + value= "'" + value + "'"; //$NON-NLS-1$//$NON-NLS-2$ + } + else { + value= value.replaceAll("\"", "\\\\\""); //$NON-NLS-1$//$NON-NLS-2$ + value= "\"" + value + "\""; //$NON-NLS-1$ //$NON-NLS-2$ + } + } commandAsString += optionPair.getKey() + SINGLE_SPACE + value + SINGLE_SPACE; } } diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/TraceUtil.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/TraceUtil.java index 3011af77d56..cde0c5b6231 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/TraceUtil.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/TraceUtil.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig.util; @@ -42,9 +43,19 @@ public class TraceUtil { return SCANNER_CONFIG; } + public static void outputTrace(String prefix, String[] tokens, String postfix) { + if (isTracing()) { + System.out.print(prefix + ' '); + for (int i = 0; i < tokens.length; i++) { + System.out.print(tokens[i] + ' '); + + } + System.out.println(postfix); + } + } + public static void outputTrace(String prefix, String msg, String postfix) { if (isTracing()) { - //System.out.println(); System.out.println(prefix + ' ' + msg + ' ' + postfix); } } @@ -94,6 +105,17 @@ public class TraceUtil { } } + public static void outputError(String string, String[] tokens) { + if (isTracing()) { + System.out.println(); + System.out.print("Error: " + string); //$NON-NLS-1$ + for (int i = 0; i < tokens.length; i++) { + System.out.print(tokens[i] + ' '); + } + System.out.println(); + } + } + /** * @param title * @param subtitlePrefix diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/SCDMakefileGenerator.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/SCDMakefileGenerator.java index 26dedf9a4b8..76e38c4ccf2 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/SCDMakefileGenerator.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/SCDMakefileGenerator.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig2; @@ -84,7 +85,7 @@ public class SCDMakefileGenerator extends DefaultRunSIProvider { buffer.append(':'); buffer.append(ENDL); buffer.append("\t@echo begin generating scanner info for $@"+ENDL+"\t"); //$NON-NLS-1$ //$NON-NLS-2$ - buffer.append(cmd.getSCDRunnableCommand(true)); // quoteIncludePaths + buffer.append(cmd.getSCDRunnableCommand(true, true)); // quote includes and defines buffer.append(" -E -P -v -dD "); //$NON-NLS-1$ buffer.append(cmd.appliesToCPPFileType() ? "specs.cpp" : "specs.c"); //$NON-NLS-1$ //$NON-NLS-2$ buffer.append(ENDL); diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java index 571017f02af..0abe470b0ed 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java @@ -16,9 +16,10 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Vector; +import java.util.Set; import junit.framework.AssertionFailedError; import junit.framework.Test; @@ -67,12 +68,12 @@ public class BaseTestCase extends TestCase { private static Test getFailingTests(Class clazz, String prefix) { TestSuite suite= new TestSuite("Failing Tests"); - Vector names= new Vector(); + HashSet names= new HashSet(); Class superClass= clazz; while (Test.class.isAssignableFrom(superClass) && !TestCase.class.equals(superClass)) { Method[] methods= superClass.getDeclaredMethods(); for (int i= 0; i < methods.length; i++) { - addFailingMethod(suite, methods[i], clazz, prefix); + addFailingMethod(suite, methods[i], names, clazz, prefix); } superClass= superClass.getSuperclass(); } @@ -82,8 +83,11 @@ public class BaseTestCase extends TestCase { return suite; } - private static void addFailingMethod(TestSuite suite, Method m, Class clazz, String prefix) { + private static void addFailingMethod(TestSuite suite, Method m, Set names, Class clazz, String prefix) { String name= m.getName(); + if (!names.add(name)) { + return; + } if (name.startsWith("test") || (prefix != null && !name.startsWith(prefix))) { return; }