### Eclipse Workspace Patch 1.0 #P org.eclipse.cdt.make.core Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CCommandDSC.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.cdt-build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CCommandDSC.java,v retrieving revision 1.12 diff -u -r1.12 CCommandDSC.java --- src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CCommandDSC.java 6 Mar 2007 18:48:55 -0000 1.12 +++ src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CCommandDSC.java 7 May 2007 21:07:01 -0000 @@ -14,6 +14,7 @@ import java.util.Iterator; import java.util.List; +import org.eclipse.core.resources.IProject; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -129,6 +130,22 @@ } /** + * Returns the compiler command + * @return + */ + public String getCompilerName() { + String compiler = new String(); + for (Iterator i = compilerCommand.iterator(); i.hasNext(); ) { + KVStringPair optionPair = (KVStringPair)i.next(); + if (optionPair.getKey().equals(SCDOptionsEnum.COMMAND.toString())) { + compiler = optionPair.getValue(); + break; + } + } + return compiler.trim(); + } + + /** * @return list of strings */ public List getImacrosFile() { @@ -308,5 +325,29 @@ setDiscovered(true); } } - + + public void resolveOptions(IProject project) { + ArrayList symbols = new ArrayList(); + ArrayList includes = new ArrayList(); + ArrayList quoteincludes = new ArrayList(); + for (Iterator options = compilerCommand.iterator(); options.hasNext(); ) { + KVStringPair optionPair = (KVStringPair)options.next(); + String key = optionPair.getKey(); + String value = optionPair.getValue(); + if (key.equals(SCDOptionsEnum.INCLUDE.toString())) { + includes.add(value); + } + else if (key.equals(SCDOptionsEnum.IDASH.toString())) { + quoteincludes.add(value); + } + else if (key.equals(SCDOptionsEnum.DEFINE.toString())) { + symbols.add(value); + } + } + setIncludes(CygpathTranslator.translateIncludePaths(project, includes)); + setQuoteIncludes(CygpathTranslator.translateIncludePaths(project, quoteincludes)); + setSymbols(symbols); + + setDiscovered(true); + } } Index: src/org/eclipse/cdt/make/internal/core/scannerconfig2/PerFileSICollector.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.cdt-build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/PerFileSICollector.java,v retrieving revision 1.19 diff -u -r1.19 PerFileSICollector.java --- src/org/eclipse/cdt/make/internal/core/scannerconfig2/PerFileSICollector.java 15 Mar 2007 17:34:32 -0000 1.19 +++ src/org/eclipse/cdt/make/internal/core/scannerconfig2/PerFileSICollector.java 7 May 2007 21:07:02 -0000 @@ -39,6 +39,7 @@ import org.eclipse.cdt.make.internal.core.scannerconfig.ScannerConfigUtil; import org.eclipse.cdt.make.internal.core.scannerconfig.util.CCommandDSC; import org.eclipse.cdt.make.internal.core.scannerconfig.util.CygpathTranslator; +import org.eclipse.cdt.make.internal.core.scannerconfig.util.KVStringPair; import org.eclipse.cdt.make.internal.core.scannerconfig.util.TraceUtil; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; @@ -229,9 +230,10 @@ addScannerInfo(((Integer)resource), scannerInfo); return; } - else if (!(resource instanceof IFile)) { - errorMessage = "resource is not an IFile";//$NON-NLS-1$ - } +// GSA allow per project settings +// else if (!(resource instanceof IFile)) { +// errorMessage = "resource is not an IFile";//$NON-NLS-1$ +// } else if (((IFile) resource).getProject() == null) { errorMessage = "project is null";//$NON-NLS-1$ } @@ -242,19 +244,21 @@ TraceUtil.outputError("PerFileSICollector.contributeToScannerConfig : ", errorMessage); //$NON-NLS-1$ return; } - IFile file = (IFile) resource; - - for (Iterator i = scannerInfo.keySet().iterator(); i.hasNext(); ) { - ScannerInfoTypes type = (ScannerInfoTypes) i.next(); - if (type.equals(ScannerInfoTypes.COMPILER_COMMAND)) { - List commands = (List) scannerInfo.get(type); - for (Iterator j = commands.iterator(); j.hasNext(); ) { - addCompilerCommand(file, (CCommandDSC) j.next()); - } - } - else { - addScannerInfo(type, (List) scannerInfo.get(type)); - } + if (resource instanceof IFile) { + IFile file = (IFile) resource; + + for (Iterator i = scannerInfo.keySet().iterator(); i.hasNext(); ) { + ScannerInfoTypes type = (ScannerInfoTypes) i.next(); + if (type.equals(ScannerInfoTypes.COMPILER_COMMAND)) { + List commands = (List) scannerInfo.get(type); + for (Iterator j = commands.iterator(); j.hasNext(); ) { + addCompilerCommand(file, (CCommandDSC) j.next()); + } + } + else { + addScannerInfo(type, (List) scannerInfo.get(type)); + } + } } } @@ -336,6 +340,10 @@ if (fileSet == null) { fileSet = new HashSet(); sid.commandIdToFilesMap.put(commandId, fileSet); + CCommandDSC cmd = (CCommandDSC) sid.commandIdCommandMap.get(commandId); + if (cmd != null) { + cmd.resolveOptions(project); + } } if (fileSet.add(file)) { // update fileToCommandIdsMap 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.16 diff -u -r1.16 GCCPerFileBOPConsoleParser.java --- src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java 24 Apr 2007 15:47:21 -0000 1.16 +++ src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java 7 May 2007 21:07:01 -0000 @@ -41,6 +41,9 @@ private String[] compilerInvocation; private GCCPerFileBOPConsoleParserUtility fUtil; + /* (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) + */ public void startup(IProject project, IPath workingDirectory, IScannerInfoCollector collector, IMarkerGenerator markerGenerator) { fUtil = (project != null && workingDirectory != null && markerGenerator != null) ? new GCCPerFileBOPConsoleParserUtility(project, workingDirectory, markerGenerator) : null; @@ -50,10 +53,16 @@ compilerInvocation = getCompilerCommands(); } + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.gnu.AbstractGCCBOPConsoleParser#getUtility() + */ protected AbstractGCCBOPConsoleParserUtility getUtility() { 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; // GCC C/C++ compiler invocation @@ -66,86 +75,84 @@ if (compilerInvocationIndex == -1) return rc; - // Search for the compiler invocation command - - // expecting that compiler invocation is the first token in the line - String[] split = line.split("\\s+"); //$NON-NLS-1$ - boolean found = false; - for (int i = 0; i < split.length; ++i) { - String command = split[i]; + // 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) { - found = true; - if (i > 0) { - // strip off anything before the compiler command - String[] old = split; - split = new String[old.length - i]; - System.arraycopy(old, i, split, 0, split.length); - } - break; - } + cii2 = command.indexOf(compilerInvocation[cii]); + if (cii2 >= 0) + break; } - if (found) - break; - } - if (!found) { + if (cii2 >= 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; - found = false; + 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; } } } - +// 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; } - // sanity check if (filePath.indexOf(FILE_EXTENSIONS[extensionsIndex]) == -1) { TraceUtil.outputTrace("Error identifying file name :2", line, TraceUtil.EOL); //$NON-NLS-1$ return rc; } - if (fUtil != null) { IPath pFilePath = fUtil.getAbsolutePath(filePath); 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(); @@ -173,4 +180,127 @@ 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(); + 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 && startPos >= compilerInvocationIndex) { + split.add(line.substring(startPos, endPos)); + } + } + return split; + } } Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParser.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.cdt-build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParser.java,v retrieving revision 1.8 diff -u -r1.8 AbstractGCCBOPConsoleParser.java --- src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParser.java 6 Mar 2007 18:48:55 -0000 1.8 +++ src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParser.java 7 May 2007 21:07:00 -0000 @@ -83,9 +83,20 @@ */ public boolean processLine(String line) { boolean rc = false; + int lineBreakPos = line.length()-1; + char[] lineChars = line.toCharArray(); + while(lineBreakPos >= 0 && Character.isWhitespace(lineChars[lineBreakPos])) { + lineBreakPos--; + } + if (lineBreakPos >= 0) { + if (lineChars[lineBreakPos] != '\\' + || (lineBreakPos > 0 && lineChars[lineBreakPos-1] == '\\')) { + lineBreakPos = -1; + } + } // check for multiline commands (ends with '\') - if (line.endsWith("\\")) { //$NON-NLS-1$ - sMultiline += line.substring(0, line.length()-1);// + " "; + if (lineBreakPos >= 0) { + sMultiline += line.substring(0, lineBreakPos); bMultiline = true; return rc; } Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParserUtility.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.cdt-build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParserUtility.java,v retrieving revision 1.10 diff -u -r1.10 GCCPerFileBOPConsoleParserUtility.java --- src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParserUtility.java 6 Mar 2007 18:48:55 -0000 1.10 +++ src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParserUtility.java 7 May 2007 21:07:01 -0000 @@ -111,7 +111,8 @@ return; compiledFileList.add(longFileName); - CCommandDSC command = getNewCCommandDSC(genericLine, false); // assume .c file type + String[] tokens = genericLine.split("\\s+"); //$NON-NLS-1$ + CCommandDSC command = getNewCCommandDSC(tokens, false); // assume .c file type int index = commandsList2.indexOf(command); if (index == -1) { commandsList2.add(command); @@ -130,9 +131,8 @@ * @param cppFileType * @return CCommandDSC compile command description */ - public CCommandDSC getNewCCommandDSC(String genericLine, boolean cppFileType) { + public CCommandDSC getNewCCommandDSC(String[] tokens, boolean cppFileType) { CCommandDSC command = new CCommandDSC(cppFileType); - String[] tokens = genericLine.split("\\s+"); //$NON-NLS-1$ command.addSCOption(new KVStringPair(SCDOptionsEnum.COMMAND.toString(), tokens[0])); for (int i = 1; i < tokens.length; ++i) { String token = tokens[i];