diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/AllCoreTests.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/AllCoreTests.java
index 7d1d2e5bb28..f4c36c309be 100644
--- a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/AllCoreTests.java
+++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/AllCoreTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 QNX Software Systems and others.
+ * Copyright (c) 2000, 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
@@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.model.tests;
@@ -42,6 +43,7 @@ public class AllCoreTests {
suite.addTest(CModelElementsTests.suite());
suite.addTest(CModelIdentifierTests.suite());
suite.addTest(CModelExceptionTest.suite());
+ suite.addTest(CModelBuilderInactiveCodeTest.suite());
suite.addTest(FlagTests.suite());
suite.addTest(ArchiveTests.suite());
suite.addTest(TranslationUnitTests.suite());
diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelBuilderInactiveCodeTest.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelBuilderInactiveCodeTest.java
new file mode 100644
index 00000000000..d6f77a46eeb
--- /dev/null
+++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelBuilderInactiveCodeTest.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Wind River Systems, Inc. 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:
+ * Markus Schorn (Wind River Systems) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core.model.tests;
+
+import junit.framework.Test;
+
+import org.eclipse.cdt.core.dom.IPDOMManager;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.IInclude;
+import org.eclipse.cdt.core.model.IMacro;
+import org.eclipse.cdt.core.model.ISourceReference;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.testplugin.CProjectHelper;
+import org.eclipse.cdt.core.testplugin.CTestPlugin;
+import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
+
+/**
+ * Tests for C model inactive code parsing.
+ */
+public class CModelBuilderInactiveCodeTest extends BaseTestCase {
+
+ public static Test suite() {
+ return suite(CModelBuilderInactiveCodeTest.class, "_");
+ }
+
+ private ICProject fCProject;
+ private ITranslationUnit fTU;
+
+ public CModelBuilderInactiveCodeTest(String name) {
+ super(name);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ fCProject= CProjectHelper.createCProject(getName(), null, IPDOMManager.ID_FAST_INDEXER);
+ assertNotNull(fCProject);
+ CProjectHelper.importSourcesFromPlugin(fCProject, CTestPlugin.getDefault().getBundle(), "/resources/cmodel");
+ fTU= (ITranslationUnit) CProjectHelper.findElement(fCProject, "CModelBuilderInactiveCodeTest.cpp");
+ assertNotNull(fTU);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ CProjectHelper.delete(fCProject);
+ super.tearDown();
+ }
+
+ public void testPreprocessorNodes() throws Exception {
+ ISourceReference e= (ISourceReference) fTU.getElement("include");
+ assertTrue(e instanceof IInclude);
+ assertFalse(e.isActive());
+
+ e= (ISourceReference) fTU.getElement("MACRO1");
+ assertTrue(e instanceof IMacro);
+ assertFalse(e.isActive());
+
+ e= (ISourceReference) fTU.getElement("MACRO2");
+ assertTrue(e instanceof IMacro);
+ assertFalse(e.isActive());
+ }
+}
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/InactiveCodeTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/InactiveCodeTests.java
new file mode 100644
index 00000000000..540dfdcd605
--- /dev/null
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/InactiveCodeTests.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Wind River Systems, Inc. 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:
+ * Markus Schorn - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core.parser.tests.scanner;
+
+import junit.framework.TestSuite;
+
+import org.eclipse.cdt.core.parser.IToken;
+
+
+/**
+ * Tests for using the preprocessor on inactive code
+ */
+public class InactiveCodeTests extends PreprocessorTestsBase {
+
+ public static TestSuite suite() {
+ return suite(InactiveCodeTests.class);
+ }
+
+ @Override
+ protected void initializeScanner() throws Exception {
+ super.initializeScanner();
+ fScanner.setProcessInactiveCode(true);
+ }
+
+ private void validate(char[] activeInactive) throws Exception {
+ boolean active= true;
+ for (char c : activeInactive) {
+ switch(c) {
+ case 'a':
+ if (!active) {
+ validateToken(IToken.tINACTIVE_CODE_END);
+ active= true;
+ }
+ validateIdentifier("a");
+ break;
+ case 'i':
+ validateToken(active ? IToken.tINACTIVE_CODE_START : IToken.tINACTIVE_CODE_SEPARATOR);
+ active= false;
+ validateIdentifier("i");
+ break;
+ default:
+ fail();
+ }
+ }
+ }
+
+
+ // #define D
+ // #ifdef D
+ // a
+ // #elif 1
+ // i
+ // #elif 0
+ // i
+ // #else
+ // i
+ // #endif
+ // a
+ // #ifdef UD
+ // i
+ // #elif 1
+ // a
+ // #elif 0
+ // i
+ // #else
+ // i
+ // #endif
+ // a
+ // #ifdef UD
+ // i
+ // #elif 0
+ // i
+ // #elif 1
+ // a
+ // #else
+ // i
+ // #endif
+ // a
+ // #ifdef UD
+ // i
+ // #elif 0
+ // i
+ // #else
+ // a
+ // #endif
+ public void testIfDef() throws Exception {
+ initializeScanner();
+ validate("aiiiaiaiiaiiaiaiia".toCharArray());
+ validateEOF();
+ }
+
+ // #define D
+ // #ifndef UD
+ // a
+ // #elif 1
+ // i
+ // #elif 0
+ // i
+ // #else
+ // i
+ // #endif
+ // a
+ // #ifndef D
+ // i
+ // #elif 1
+ // a
+ // #elif 0
+ // i
+ // #else
+ // i
+ // #endif
+ // a
+ // #ifndef D
+ // i
+ // #elif 0
+ // i
+ // #elif 1
+ // a
+ // #else
+ // i
+ // #endif
+ // a
+ // #ifndef D
+ // i
+ // #elif 0
+ // i
+ // #else
+ // a
+ // #endif
+ public void testIfnDef() throws Exception {
+ initializeScanner();
+ validate("aiiiaiaiiaiiaiaiia".toCharArray());
+ validateEOF();
+ }
+
+ // #if 1
+ // a
+ // #elif 1
+ // i
+ // #elif 0
+ // i
+ // #else
+ // i
+ // #endif
+ // a
+ // #if 0
+ // i
+ // #elif 1
+ // a
+ // #elif 0
+ // i
+ // #else
+ // i
+ // #endif
+ // a
+ // #if 0
+ // i
+ // #elif 0
+ // i
+ // #elif 1
+ // a
+ // #else
+ // i
+ // #endif
+ // a
+ // #if 0
+ // i
+ // #elif 0
+ // i
+ // #else
+ // a
+ // #endif
+ public void testIf() throws Exception {
+ initializeScanner();
+ validate("aiiiaiaiiaiiaiaiia".toCharArray());
+ validateEOF();
+ }
+
+ // #if 0
+ // i
+ // #if 1
+ // i
+ // #elif 0
+ // i
+ // #else
+ // i
+ // #endif
+ // i
+ // #endif
+ // a
+ // #if 0
+ // i
+ // #if 0
+ // i
+ // #elif 1
+ // i
+ // #else
+ // i
+ // #endif
+ // i
+ // #endif
+ // a
+ // #if 0
+ // i
+ // #if 0
+ // i
+ // #elif 0
+ // i
+ // #else
+ // i
+ // #endif
+ // i
+ // #endif
+ // a
+ public void testNestedInInactive() throws Exception {
+ initializeScanner();
+ validate("iiiiiaiiiiiaiiiiia".toCharArray());
+ validateEOF();
+ }
+
+ // #if 0
+ // i
+ // #define M
+ // #endif
+ // a
+ // #ifdef M
+ // i
+ // #endif
+ // a
+ public void testInactiveMacroDefinition() throws Exception {
+ initializeScanner();
+ validate("iaia".toCharArray());
+ validateEOF();
+ assertNull(fScanner.getMacroDefinitions().get("M"));
+ }
+
+ // #ifdef X
+ // # if 0
+ // # endif
+ // #elif defined (Y)
+ // #endif
+ public void testDefinedSyntax() throws Exception {
+ initializeScanner();
+ validateToken(IToken.tINACTIVE_CODE_START);
+ fScanner.skipInactiveCode();
+ validateEOF();
+ validateProblemCount(0);
+ }
+}
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java
index ef05190e6ec..2cbd0948e17 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2009 Wind River Systems, Inc. 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
@@ -408,8 +408,8 @@ public class LocationMapTests extends BaseTestCase {
final String[] params = new String[]{"p1", "p2"};
IMacroBinding macro2= new TestMacro("n2", "exp2", params);
init(DIGITS);
- fLocationMap.encounterPoundDefine(0, 0, 0, 0, 0, macro1);
- fLocationMap.encounterPoundDefine(0, 1, 3, 10, 16, macro2);
+ fLocationMap.encounterPoundDefine(0, 0, 0, 0, 0, true, macro1);
+ fLocationMap.encounterPoundDefine(0, 1, 3, 10, 16, true, macro2);
IASTPreprocessorMacroDefinition[] prep= fLocationMap.getMacroDefinitions();
assertEquals(2, prep.length);
checkMacroDefinition(prep[0], macro1, "", "n1", "", "exp1", null, FN, 0, 0, 1, 0, 0);
@@ -463,7 +463,7 @@ public class LocationMapTests extends BaseTestCase {
assertEquals(2, fLocationMap.getCurrentLineNumber('\n'+1));
fLocationMap.registerPredefinedMacro(macro1);
fLocationMap.registerMacroFromIndex(macro2, new Loc("ifile", 2, 12), 32);
- fLocationMap.encounterPoundDefine(3, 13, 33, 63, 103, macro3);
+ fLocationMap.encounterPoundDefine(3, 13, 33, 63, 103, true, macro3);
IASTName name1= fLocationMap.encounterImplicitMacroExpansion(macro1, null);
IASTName name2= fLocationMap.encounterImplicitMacroExpansion(macro2, null);
fLocationMap.pushMacroExpansion(110, 115, 125, 30, macro3, new IASTName[]{name1, name2}, new ImageLocationInfo[0]);
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java
index 290588438d6..05de0774722 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2009 Wind River Systems, Inc. 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
@@ -24,6 +24,7 @@ public class ScannerTestSuite extends TestSuite {
suite.addTest(InclusionTests.suite());
suite.addTest(PreprocessorBugsTests.suite());
suite.addTest(ExpansionExplorerTests.suite());
+ suite.addTest(InactiveCodeTests.suite());
return suite;
}
}
diff --git a/core/org.eclipse.cdt.core.tests/resources/cmodel/CModelBuilderInactiveCodeTest.cpp b/core/org.eclipse.cdt.core.tests/resources/cmodel/CModelBuilderInactiveCodeTest.cpp
new file mode 100644
index 00000000000..a3f269294e9
--- /dev/null
+++ b/core/org.eclipse.cdt.core.tests/resources/cmodel/CModelBuilderInactiveCodeTest.cpp
@@ -0,0 +1,5 @@
+#if 0
+#include "include"
+#define MACRO1 1
+#define MACRO2(x, y) x+y
+#endif
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInclude.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInclude.java
index 52a9b4bc67a..e5a9ee76d15 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInclude.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInclude.java
@@ -37,12 +37,6 @@ public interface IInclude extends ICElement, ISourceReference, ISourceManipulati
public boolean isLocal();
- /**
- * @return whether this include directive is in active code, ie. not hidden
- * by conditional compilation
- */
- public boolean isActive();
-
/**
* @return whether this include directive was resolved and followed.
*/
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ILanguage.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ILanguage.java
index 7a17447690b..a8329ae56c0 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ILanguage.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ILanguage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2008 QNX Software Systems and others.
+ * Copyright (c) 2005, 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
@@ -47,7 +47,7 @@ public interface ILanguage extends IAdaptable {
/**
* Option for {@link #getASTTranslationUnit(CodeReader, IScannerInfo, ICodeReaderFactory, IIndex, int, IParserLogService)}
- * Performance optimization, instructs the parser not to create image-locations.
+ * Performance optimization, allows the parser not to create image-locations.
* When using this option {@link IASTName#getImageLocation()} will always return null
.
*/
public final static int OPTION_NO_IMAGE_LOCATIONS= 0x4;
@@ -61,12 +61,21 @@ public interface ILanguage extends IAdaptable {
/**
* Option for {@link #getASTTranslationUnit(CodeReader, IScannerInfo, ICodeReaderFactory, IIndex, int, IParserLogService)}
- * Instructs the parser not to create ast nodes for expressions within aggregate initializers
+ * Allows the parser not to create ast nodes for expressions within aggregate initializers
* when they do not contain names.
* @since 5.1
*/
public final static int OPTION_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS= 0x10;
+ /**
+ * Option for {@link #getASTTranslationUnit(CodeReader, IScannerInfo, ICodeReaderFactory, IIndex, int, IParserLogService)}
+ * Instructs the parser to create ast nodes for inactive code branches, if possible. There is no guarantee that the ast
+ * can actually be created for the inactive parts.
+ * mstodo document how the ast can be accessed.
+ * @since 5.1
+ */
+ public final static int OPTION_PARSE_INACTIVE_CODE= 0x20;
+
/**
* Return the language id for this language.
* This is to differentiate languages from each other.
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceReference.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceReference.java
index 6602afaae06..f721ca3a58e 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceReference.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceReference.java
@@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.model;
@@ -56,4 +57,17 @@ public interface ISourceReference {
* if this member is not declared in a translation unit (for example, a binary type).
*/
ITranslationUnit getTranslationUnit();
+
+ /**
+ * Returns whether this element is in active code. Code is inactive when it is hidden
+ * by conditional compilation.
+ * @since 5.1
+ */
+ public boolean isActive();
+
+ /**
+ * Allows to differentiate otherwise equal elements of the same file.
+ * @since 5.1
+ */
+ int getIndex();
}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java
index 0b452099325..c84f0df79af 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2007 QNX Software Systems and others.
+ * Copyright (c) 2000, 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
@@ -95,6 +95,14 @@ public interface ITranslationUnit extends ICElement, IParent, IOpenable, ISource
*/
public final static int AST_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS= 0x40;
+ /**
+ * Style constant for {@link #getAST(IIndex, int)}.
+ * Instructs the parser to make an attempt to create ast nodes for inactive code branches.
+ * mstodo document how to access those.
+ * @since 5.1
+ */
+ public final static int AST_PARSE_INACTIVE_CODE= 0x80;
+
/**
* Creates and returns an include declaration in this translation unit
* with the given name.
@@ -167,9 +175,24 @@ public interface ITranslationUnit extends ICElement, IParent, IOpenable, ISource
* @return the found shared working copy for this element, null
if none
* @see IBufferFactory
* @since 2.0
+ * @noreference This method is not intended to be referenced by clients.
*/
IWorkingCopy findSharedWorkingCopy(IBufferFactory bufferFactory);
+ /**
+ * Returns the shared working copy for this element, using the default IBuffer
factory, or
+ * null
, if no working copy has been created for this element.
+ *
+ * Users of this method must not destroy the resulting working copy.
+ *
+ * @param bufferFactory
+ * the given IBuffer
factory
+ * @return the found shared working copy for this element, or null
if none
+ * @see IBufferFactory
+ * @since 5.1
+ */
+ IWorkingCopy findSharedWorkingCopy();
+
/**
* Returns the contents of a translation unit as a char[]
* @return char[]
@@ -284,13 +307,11 @@ public interface ITranslationUnit extends ICElement, IParent, IOpenable, ISource
* @see IBufferFactory
* @see IProblemRequestor
* @since 2.0
+ * @noreference This method is not intended to be referenced by clients.
*/
+ IWorkingCopy getSharedWorkingCopy(IProgressMonitor monitor, IBufferFactory factory)
+ throws CModelException;
- IWorkingCopy getSharedWorkingCopy(
- IProgressMonitor monitor,
- IBufferFactory factory)
- throws CModelException;
-
/**
* Returns a shared working copy on this element using the given factory to create
* the buffer, or this element if this element is already a working copy.
@@ -333,9 +354,53 @@ public interface ITranslationUnit extends ICElement, IParent, IOpenable, ISource
* @see IBufferFactory
* @see IProblemRequestor
* @since 2.0
+ * @noreference This method is not intended to be referenced by clients.
*/
IWorkingCopy getSharedWorkingCopy(IProgressMonitor monitor, IBufferFactory factory, IProblemRequestor requestor) throws CModelException;
+ /**
+ * Returns a shared working copy on this element using the given factory to create the buffer, or this
+ * element if this element is already a working copy. This API can only answer an already existing working
+ * copy if it is based on the same original translation unit AND was using the same buffer factory (i.e.
+ * as defined by Object#equals
).
+ *
+ * The life time of a shared working copy is as follows: + *
getSharedWorkingCopy(...)
creates a new working copy for this
+ * elementdestroy()
decrements the internal counter.+ * Note that the buffer factory will be used for the life time of this working copy, i.e. if the working + * copy is closed then reopened, this factory will be used. The buffer will be automatically initialized + * with the original's compilation unit content upon creation. + *
+ * When the shared working copy instance is created, an ADDED ICElementDelta is reported on this working
+ * copy.
+ *
+ * @param monitor
+ * a progress monitor used to report progress while opening this compilation unit or
+ * null
if no progress should be reported
+ * @param requestor
+ * a requestor which will get notified of problems detected during reconciling as they are
+ * discovered. The requestor can be set to null
indicating that the client is not
+ * interested in problems.
+ * @exception CModelException
+ * if the contents of this element can not be determined. Reasons include:
+ *
IASTName
*/
public IASTName getName();
- /**
- * Set the macro name.
- *
- * @param name
- */
- public void setName(IASTName name);
-
/**
* Returns the macro expansion, or an empty string for dynamic style macros.
*/
@@ -53,11 +44,20 @@ public interface IASTPreprocessorMacroDefinition extends
*/
public IASTFileLocation getExpansionLocation();
+
/**
- * Set the macro expansion.
- *
- * @param exp
- * String
+ * Returns whether this macro definition occurs in active code.
+ * @since 5.1
*/
- public void setExpansion(String exp);
+ public boolean isActive();
+
+ /**
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @Deprecated public void setName(IASTName name);
+
+ /**
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @Deprecated public void setExpansion(String exp);
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java
index 717f8626dad..2f081b772b9 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * Copyright (c) 2007, 2009 IBM Corporation 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
@@ -114,6 +114,7 @@ public abstract class AbstractCLikeLanguage extends AbstractLanguage implements
final IScanner scanner= createScanner(reader, scanInfo, codeReaderFactory, log);
scanner.setComputeImageLocations((options & OPTION_NO_IMAGE_LOCATIONS) == 0);
+ scanner.setProcessInactiveCode((options & OPTION_PARSE_INACTIVE_CODE) != 0);
final ISourceCodeParser parser= createParser(scanner, log, index, false, options);
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java
index 237ab119b2d..e15c232bc9e 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2003, 2008 IBM Corporation and others.
+ * Copyright (c) 2003, 2009 IBM Corporation 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
@@ -82,4 +82,20 @@ public interface IScanner {
* @since 5.0
*/
public void setComputeImageLocations(boolean val);
+
+ /**
+ * Toggles generation of tokens for inactive code branches. When turned on,
+ * each inactive code branch is preceded by a token of kind {@link IToken#tINACTIVE_CODE_START} and
+ * succeeded by one of kind {@link IToken#tINACTIVE_CODE_END}.
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ public void setProcessInactiveCode(boolean val);
+
+ /**
+ * When in inactive code, skips all tokens up to the end of the inactive code section.
+ * Note, token after calling this method may be another token of type {@link IToken#tINACTIVE_CODE_START}. + * @noreference This method is not intended to be referenced by clients. + */ + public void skipInactiveCode() throws OffsetLimitReachedException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java index 1fad501f5d7..73f4a80081b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java @@ -39,195 +39,155 @@ public interface IToken { int FIRST_RESERVED_SCANNER= -100; int LAST_RESERVED_SCANNER= -1; - static public final int tIDENTIFIER = 1; - static public final int tINTEGER = 2; - static public final int tCOLONCOLON = 3; - static public final int tCOLON = 4; - static public final int tSEMI = 5; - static public final int tCOMMA = 6; - static public final int tQUESTION = 7; - static public final int tLPAREN = 8; - static public final int tRPAREN = 9; - static public final int tLBRACKET = 10; - static public final int tRBRACKET = 11; - static public final int tLBRACE = 12; - static public final int tRBRACE = 13; - static public final int tPLUSASSIGN = 14; - static public final int tINCR = 15; - static public final int tPLUS = 16; - static public final int tMINUSASSIGN = 17; - static public final int tDECR = 18; - static public final int tARROWSTAR = 19; - static public final int tARROW = 20; - static public final int tMINUS = 21; - static public final int tSTARASSIGN = 22; - static public final int tSTAR = 23; - static public final int tMODASSIGN = 24; - static public final int tMOD = 25; - static public final int tXORASSIGN = 26; - static public final int tXOR = 27; - static public final int tAMPERASSIGN = 28; - static public final int tAND = 29; - static public final int tAMPER = 30; - static public final int tBITORASSIGN = 31; - static public final int tOR = 32; - static public final int tBITOR = 33; - static public final int tBITCOMPLEMENT = 34; - static public final int tNOTEQUAL = 35; - static public final int tNOT = 36; - static public final int tEQUAL = 37; - static public final int tASSIGN = 38; - static public final int tUNKNOWN_CHAR= 39; - static public final int tSHIFTL = 40; - static public final int tLTEQUAL = 41; - static public final int tLT = 42; - static public final int tSHIFTRASSIGN = 43; - static public final int tSHIFTR = 44; - static public final int tGTEQUAL = 45; - static public final int tGT = 46; - static public final int tSHIFTLASSIGN = 47; - static public final int tELLIPSIS = 48; - static public final int tDOTSTAR = 49; - static public final int tDOT = 50; - static public final int tDIVASSIGN = 51; - static public final int tDIV = 52; + int tIDENTIFIER = 1; + int tINTEGER = 2; + int tCOLONCOLON = 3; + int tCOLON = 4; + int tSEMI = 5; + int tCOMMA = 6; + int tQUESTION = 7; + int tLPAREN = 8; + int tRPAREN = 9; + int tLBRACKET = 10; + int tRBRACKET = 11; + int tLBRACE = 12; + int tRBRACE = 13; + int tPLUSASSIGN = 14; + int tINCR = 15; + int tPLUS = 16; + int tMINUSASSIGN = 17; + int tDECR = 18; + int tARROWSTAR = 19; + int tARROW = 20; + int tMINUS = 21; + int tSTARASSIGN = 22; + int tSTAR = 23; + int tMODASSIGN = 24; + int tMOD = 25; + int tXORASSIGN = 26; + int tXOR = 27; + int tAMPERASSIGN = 28; + int tAND = 29; + int tAMPER = 30; + int tBITORASSIGN = 31; + int tOR = 32; + int tBITOR = 33; + int tBITCOMPLEMENT = 34; + int tNOTEQUAL = 35; + int tNOT = 36; + int tEQUAL = 37; + int tASSIGN = 38; + int tUNKNOWN_CHAR= 39; + int tSHIFTL = 40; + int tLTEQUAL = 41; + int tLT = 42; + int tSHIFTRASSIGN = 43; + int tSHIFTR = 44; + int tGTEQUAL = 45; + int tGT = 46; + int tSHIFTLASSIGN = 47; + int tELLIPSIS = 48; + int tDOTSTAR = 49; + int tDOT = 50; + int tDIVASSIGN = 51; + int tDIV = 52; - /** @deprecated use {@link #tAND} */ - @Deprecated - static public final int t_and = 54; - /** @deprecated use {@link #tAMPERASSIGN} */ - @Deprecated - static public final int t_and_eq = 55; - - static public final int t_asm = 56; - static public final int t_auto = 57; - - /** @deprecated use {@link #tAMPER} */ - @Deprecated - static public final int t_bitand = 58; - /** @deprecated use {@link #tBITOR} */ - @Deprecated - static public final int t_bitor = 59; - - static public final int t_bool = 60; - static public final int t_break = 61; - static public final int t_case = 62; - static public final int t_catch = 63; - static public final int t_char = 64; - static public final int t_class = 65; + /** @deprecated use {@link #tAND} */ @Deprecated int t_and = 54; + /** @deprecated use {@link #tAMPERASSIGN} */ @Deprecated int t_and_eq = 55; + int t_asm = 56; + int t_auto = 57; + /** @deprecated use {@link #tAMPER} */ @Deprecated int t_bitand = 58; + /** @deprecated use {@link #tBITOR} */ @Deprecated int t_bitor = 59; + int t_bool = 60; + int t_break = 61; + int t_case = 62; + int t_catch = 63; + int t_char = 64; + int t_class = 65; + /** @deprecated use {@link #tBITCOMPLEMENT} */ @Deprecated int tCOMPL= tBITCOMPLEMENT; + /** @deprecated use {@link #tBITCOMPLEMENT} */ @Deprecated int t_compl = 66; + int t_const = 67; - /** @deprecated use {@link #tBITCOMPLEMENT} */ - @Deprecated - static public final int tCOMPL= tBITCOMPLEMENT; - /** @deprecated use {@link #tBITCOMPLEMENT} */ - @Deprecated - static public final int t_compl = 66; - - static public final int t_const = 67; - static public final int t_const_cast = 69; - static public final int t_continue = 70; - static public final int t_default = 71; - static public final int t_delete = 72; - static public final int t_do = 73; - static public final int t_double = 74; - static public final int t_dynamic_cast = 75; - static public final int t_else = 76; - static public final int t_enum = 77; - static public final int t_explicit = 78; - static public final int t_export = 79; - static public final int t_extern = 80; - static public final int t_false = 81; - static public final int t_float = 82; - static public final int t_for = 83; - static public final int t_friend = 84; - static public final int t_goto = 85; - static public final int t_if = 86; - static public final int t_inline = 87; - static public final int t_int = 88; - static public final int t_long = 89; - static public final int t_mutable = 90; - static public final int t_namespace = 91; - static public final int t_new = 92; - - /** @deprecated use {@link #tNOT} */ - @Deprecated - static public final int t_not = 93; - /** @deprecated use {@link #tNOTEQUAL} */ - @Deprecated - static public final int t_not_eq = 94; - - static public final int t_operator = 95; - - /** @deprecated use {@link #tOR} */ - @Deprecated - static public final int t_or = 96; - /** @deprecated use {@link #tBITORASSIGN} */ - @Deprecated - static public final int t_or_eq = 97; - - static public final int t_private = 98; - static public final int t_protected = 99; - static public final int t_public = 100; - static public final int t_register = 101; - static public final int t_reinterpret_cast = 102; - static public final int t_return = 103; - static public final int t_short = 104; - static public final int t_sizeof = 105; - static public final int t_static = 106; - static public final int t_static_cast = 107; - static public final int t_signed = 108; - static public final int t_struct = 109; - static public final int t_switch = 110; - static public final int t_template = 111; - static public final int t_this = 112; - static public final int t_throw = 113; - static public final int t_true = 114; - static public final int t_try = 115; - static public final int t_typedef = 116; - static public final int t_typeid = 117; - static public final int t_typename = 118; - static public final int t_union = 119; - static public final int t_unsigned = 120; - static public final int t_using = 121; - static public final int t_virtual = 122; - static public final int t_void = 123; - static public final int t_volatile = 124; - static public final int t_wchar_t = 125; - static public final int t_while = 126; - - /** @deprecated use {@link #tXOR} */ - @Deprecated - static public final int t_xor = 127; - /** @deprecated use {@link #tXORASSIGN} */ - @Deprecated - static public final int t_xor_eq = 128; - - static public final int tFLOATINGPT = 129; - static public final int tSTRING = 130; - static public final int tLSTRING = 131; - static public final int tCHAR = 132; - static public final int tLCHAR = 133; - static public final int t__Bool = 134; - static public final int t__Complex = 135; - static public final int t__Imaginary = 136; - static public final int t_restrict = 137; - - /** @deprecated don't use it */ - @Deprecated - static public final int tMACROEXP = 138; - - static public final int tPOUND= 138; - static public final int tPOUNDPOUND = 139; - static public final int tCOMPLETION = 140; - static public final int tEOC = 141; // End of Completion - - /** @deprecated don't use it */ - @Deprecated - static public final int tCOMMENT = 142; - /** @deprecated don't use it */ - @Deprecated - static public final int tBLOCKCOMMENT = 143; - static public final int tEND_OF_INPUT= 144; + int t_const_cast = 69; + int t_continue = 70; + int t_default = 71; + int t_delete = 72; + int t_do = 73; + int t_double = 74; + int t_dynamic_cast = 75; + int t_else = 76; + int t_enum = 77; + int t_explicit = 78; + int t_export = 79; + int t_extern = 80; + int t_false = 81; + int t_float = 82; + int t_for = 83; + int t_friend = 84; + int t_goto = 85; + int t_if = 86; + int t_inline = 87; + int t_int = 88; + int t_long = 89; + int t_mutable = 90; + int t_namespace = 91; + int t_new = 92; + /** @deprecated use {@link #tNOT} */ @Deprecated int t_not = 93; + /** @deprecated use {@link #tNOTEQUAL} */ @Deprecated int t_not_eq = 94; + int t_operator = 95; + /** @deprecated use {@link #tOR} */ @Deprecated int t_or = 96; + /** @deprecated use {@link #tBITORASSIGN} */ @Deprecated int t_or_eq = 97; + int t_private = 98; + int t_protected = 99; + int t_public = 100; + int t_register = 101; + int t_reinterpret_cast = 102; + int t_return = 103; + int t_short = 104; + int t_sizeof = 105; + int t_static = 106; + int t_static_cast = 107; + int t_signed = 108; + int t_struct = 109; + int t_switch = 110; + int t_template = 111; + int t_this = 112; + int t_throw = 113; + int t_true = 114; + int t_try = 115; + int t_typedef = 116; + int t_typeid = 117; + int t_typename = 118; + int t_union = 119; + int t_unsigned = 120; + int t_using = 121; + int t_virtual = 122; + int t_void = 123; + int t_volatile = 124; + int t_wchar_t = 125; + int t_while = 126; + /** @deprecated use {@link #tXOR} */ @Deprecated int t_xor = 127; + /** @deprecated use {@link #tXORASSIGN} */ @Deprecated int t_xor_eq = 128; + int tFLOATINGPT = 129; + int tSTRING = 130; + int tLSTRING = 131; + int tCHAR = 132; + int tLCHAR = 133; + int t__Bool = 134; + int t__Complex = 135; + int t__Imaginary = 136; + int t_restrict = 137; + /** @deprecated don't use it */ @Deprecated int tMACROEXP = 138; + int tPOUND= 138; + int tPOUNDPOUND = 139; + int tCOMPLETION = 140; + int tEOC = 141; // End of Completion + /** @deprecated don't use it */ @Deprecated int tCOMMENT = 142; + /** @deprecated don't use it */ @Deprecated int tBLOCKCOMMENT = 143; + int tEND_OF_INPUT= 144; + /** @since 5.1 */ int tINACTIVE_CODE_START= 145; + /** @since 5.1 */ int tINACTIVE_CODE_SEPARATOR= 146; + /** @since 5.1 */ int tINACTIVE_CODE_END = 147; int FIRST_RESERVED_IGCCToken = 150; int LAST_RESERVED_IGCCToken = 199; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 663b219f51f..08f5f810a1d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation 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 @@ -206,29 +206,35 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } /** - * Look Ahead in the token list to see what is coming. - * - * @param i - * How far ahead do you wish to peek? + * Returns the next token without advancing + */ + protected IToken mark() throws EndOfFileException { + return currToken == null ? currToken = fetchToken(true) : currToken; + } + + /** + * Roll back to a previous point, reseting the queue of tokens. + * @param mark a token previously obtained via {@link #mark()}. + */ + protected void backup(IToken mark) { + currToken = mark; + } + + /** + * Look ahead in the token list to see what is coming. + * @param i number of tokens to look ahead, must be greater or equal to 0. * @return the token you wish to observe - * @throws EndOfFileException - * if looking ahead encounters EOF, throw EndOfFile */ protected IToken LA(int i) throws EndOfFileException { - + assert i >= 0; if (isCancelled) { throw new ParseError(ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); } - - if (i < 1) // can't go backwards - return null; - if (currToken == null) - currToken = fetchToken(); - IToken retToken = currToken; + IToken retToken= mark(); for (; i > 1; --i) { retToken = retToken.getNext(); if (retToken == null) - retToken = fetchToken(); + retToken = fetchToken(true); } return retToken; } @@ -246,12 +252,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { /** * Look ahead in the token list and return the token type. - * - * @param i - * How far ahead do you wish to peek? + * @param i number of tokens to look ahead, must be greater or equal to 0. * @return The type of that token - * @throws EndOfFileException - * if looking ahead encounters EOF, throw EndOfFile */ protected int LT(int i) throws EndOfFileException { return LA(i).getType(); @@ -295,37 +297,29 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } /** - * Consume the next token available, regardless of the type. + * Consume the next token available, regardless of the type and returns it. * * @return The token that was consumed and removed from our buffer. * @throws EndOfFileException * If there is no token to consume. */ protected IToken consume() throws EndOfFileException { - if (currToken == null) { - currToken = fetchToken(); - } - - final IToken lastToken = currToken; - currToken= lastToken.getNext(); - return lastToken; + final IToken result= mark(); + currToken= result.getNext(); + return result; } /** - * Consume the next token available only if the type is as specified. + * If the type of the next token matches, it is consumed and returned. Otherwise a + * {@link BacktrackException} will be thrown. * - * @param type - * The type of token that you are expecting. - * @return the token that was consumed and removed from our buffer. - * @throws BacktrackException - * If LT(1) != type + * @param type the expected type of the next token. */ protected IToken consume(int type) throws EndOfFileException, BacktrackException { - final IToken la1= LA(1); - if (la1.getType() != type) - throwBacktrack(la1); - - return consume(); + final IToken result= consume(); + if (result.getType() != type) + throwBacktrack(result); + return result; } /** @@ -350,15 +344,15 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } /** - * Fetches a token from the scanner. - * - * @return the next token from the scanner - * @throws EndOfFileException - * thrown when the scanner.nextToken() yields no tokens + * Fetches the next token from the scanner. */ - protected IToken fetchToken() throws EndOfFileException { + private IToken fetchToken(boolean skipInactive) throws EndOfFileException { try { - final IToken result= scanner.nextToken(); + IToken result= scanner.nextToken(); + while (result.getType() == IToken.tINACTIVE_CODE_START) { + scanner.skipInactiveCode(); + result= scanner.nextToken(); + } eofOffset= result.getEndOffset(); return result; } catch (OffsetLimitReachedException olre) { @@ -375,28 +369,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { throw exception; } - /** - * Mark our place in the buffer so that we could return to it should we have - * to. - * - * @return The current token. - * @throws EndOfFileException - * If there are no more tokens. - */ - protected IToken mark() throws EndOfFileException { - return currToken == null ? currToken = fetchToken() : currToken; - } - - /** - * Rollback to a previous point, reseting the queue of tokens. - * - * @param mark - * The point that we wish to restore to. - */ - protected void backup(IToken mark) { - currToken = mark; - } - /** * This is the single entry point for setting parsePassed to false */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java index a0ebe901133..99b1a6deef4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 Wind River Systems, Inc. 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 @@ -276,15 +276,17 @@ class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessor private final ASTPreprocessorName fName; private final int fExpansionNumber; private final int fExpansionOffset; + private final boolean fActive; /** * Regular constructor. */ public ASTMacroDefinition(IASTTranslationUnit parent, IMacroBinding macro, - int startNumber, int nameNumber, int nameEndNumber, int expansionNumber, int endNumber) { + int startNumber, int nameNumber, int nameEndNumber, int expansionNumber, int endNumber, boolean active) { super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber); fExpansionNumber= expansionNumber; fExpansionOffset= -1; + fActive= active; fName= new ASTPreprocessorDefinition(this, IASTPreprocessorMacroDefinition.MACRO_NAME, nameNumber, nameEndNumber, macro.getNameCharArray(), macro); } @@ -297,6 +299,7 @@ class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessor fName= new ASTBuiltinName(this, IASTPreprocessorMacroDefinition.MACRO_NAME, floc, macro.getNameCharArray(), macro); fExpansionNumber= -1; fExpansionOffset= expansionOffset; + fActive= true; } @@ -357,6 +360,10 @@ class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessor public String toString() { return getName().toString() + '=' + getExpansion(); } + + final public boolean isActive() { + return fActive; + } } class ASTMacroParameter extends ASTPreprocessorNode implements IASTFunctionStyleMacroParameter { @@ -379,8 +386,8 @@ class ASTFunctionStyleMacroDefinition extends ASTMacroDefinition implements IAST * Regular constructor. */ public ASTFunctionStyleMacroDefinition(IASTTranslationUnit parent, IMacroBinding macro, - int startNumber, int nameNumber, int nameEndNumber, int expansionNumber, int endNumber) { - super(parent, macro, startNumber, nameNumber, nameEndNumber, expansionNumber, endNumber); + int startNumber, int nameNumber, int nameEndNumber, int expansionNumber, int endNumber, boolean active) { + super(parent, macro, startNumber, nameNumber, nameEndNumber, expansionNumber, endNumber, active); } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java index e5edc98f486..914604dcfdd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java @@ -49,6 +49,9 @@ import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalExce import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent.InclusionKind; import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions; import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException; +import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.BranchKind; +import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.CodeState; +import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.Conditional; import org.eclipse.core.runtime.IAdaptable; /** @@ -68,7 +71,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { private static final int ORIGIN_PREPROCESSOR_DIRECTIVE = OffsetLimitReachedException.ORIGIN_PREPROCESSOR_DIRECTIVE; private static final int ORIGIN_INACTIVE_CODE = OffsetLimitReachedException.ORIGIN_INACTIVE_CODE; -// private static final int ORIGIN_MACRO_EXPANSION = OffsetLimitReachedException.ORIGIN_MACRO_EXPANSION; private static final char[] EMPTY_CHAR_ARRAY = new char[0]; private static final char[] ONE = "1".toCharArray(); //$NON-NLS-1$ @@ -169,7 +171,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { final private String[] fIncludePaths; final private String[] fQuoteIncludePaths; private String[][] fPreIncludedFiles= null; -// private boolean fProcessInactiveCode= false; private int fContentAssistLimit= -1; private boolean fHandledCompletion= false; @@ -279,10 +280,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { fRootLexer.setContentAssistMode(offset); } - // mstodo -// public void setProcessInactiveCode(boolean val) { -// fProcessInactiveCode= val; -// } + public void setProcessInactiveCode(boolean val) { + fRootContext.setParseInactiveCode(val); + } public void setScanComments(boolean val) { } @@ -599,7 +599,19 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return t1; } - private void appendStringContent(StringBuffer buf, Token t1) { + + public void skipInactiveCode() throws OffsetLimitReachedException { + final Lexer lexer= fCurrentContext.getLexer(); + if (lexer != null) { + CodeState state= fCurrentContext.getCodeState(); + while (state != CodeState.eActive) { + state= skipBranch(lexer, false); + } + fCurrentContext.clearInactiveCodeMarkerToken(); + } + } + + private void appendStringContent(StringBuffer buf, Token t1) { final char[] image= t1.getCharImage(); final int length= image.length; if (length > 1) { @@ -940,8 +952,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { /** * Assumes that the pound token has not yet been consumed - * @param ppdCtx - * @param startOffset offset in current file * @since 5.0 */ private void executeDirective(final Lexer lexer, final int startOffset, boolean withinExpansion) throws OffsetLimitReachedException { @@ -971,77 +981,53 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } // we have an identifier - boolean isProblem= false; final char[] name = ident.getCharImage(); final int type = fPPKeywords.get(name); int condEndOffset; switch (type) { case IPreprocessorDirective.ppImport: case IPreprocessorDirective.ppInclude: - if (withinExpansion) { - isProblem= true; - } else { - executeInclude(lexer, startOffset, false, true); - } + executeInclude(lexer, startOffset, false, fCurrentContext.getCodeState() == CodeState.eActive, withinExpansion); break; case IPreprocessorDirective.ppInclude_next: - if (withinExpansion) { - isProblem= true; - } else { - executeInclude(lexer, startOffset, true, true); - } + executeInclude(lexer, startOffset, true, fCurrentContext.getCodeState() == CodeState.eActive, withinExpansion); break; case IPreprocessorDirective.ppDefine: - executeDefine(lexer, startOffset); + executeDefine(lexer, startOffset, fCurrentContext.getCodeState() == CodeState.eActive); break; case IPreprocessorDirective.ppUndef: executeUndefine(lexer, startOffset); break; case IPreprocessorDirective.ppIfdef: - executeIfdef(lexer, startOffset, true, withinExpansion); + if (executeIfdef(lexer, startOffset, false, withinExpansion) == CodeState.eSkipInactive) + skipOverConditionalCode(lexer, withinExpansion); break; case IPreprocessorDirective.ppIfndef: - executeIfdef(lexer, startOffset, false, withinExpansion); + if (executeIfdef(lexer, startOffset, true, withinExpansion) == CodeState.eSkipInactive) + skipOverConditionalCode(lexer, withinExpansion); break; case IPreprocessorDirective.ppIf: - executeIf(lexer, startOffset, withinExpansion); - break; - case IPreprocessorDirective.ppElse: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELSE)) { - fLocationMap.encounterPoundElse(startOffset, ident.getEndOffset(), false); - skipOverConditionalCode(lexer, false, withinExpansion); - } - else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, ident.getEndOffset()); - } + if (executeIf(lexer, startOffset, false, withinExpansion) == CodeState.eSkipInactive) + skipOverConditionalCode(lexer, withinExpansion); break; case IPreprocessorDirective.ppElif: - int condOffset= lexer.nextToken().getOffset(); - condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - int endOffset= lexer.currentToken().getEndOffset(); - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELIF)) { - fLocationMap.encounterPoundElif(startOffset, condOffset, condEndOffset, endOffset, false, IASTName.EMPTY_NAME_ARRAY); - skipOverConditionalCode(lexer, false, withinExpansion); - } - else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, condEndOffset); + if (executeIf(lexer, startOffset, true, withinExpansion) == CodeState.eSkipInactive) { + skipOverConditionalCode(lexer, withinExpansion); + } + break; + case IPreprocessorDirective.ppElse: + if (executeElse(lexer, startOffset, withinExpansion) == CodeState.eSkipInactive) { + skipOverConditionalCode(lexer, withinExpansion); } break; case IPreprocessorDirective.ppEndif: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_END)) { - fLocationMap.encounterPoundEndIf(startOffset, ident.getEndOffset()); - } - else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, ident.getEndOffset()); - } + executeEndif(lexer, startOffset, withinExpansion); break; case IPreprocessorDirective.ppWarning: case IPreprocessorDirective.ppError: - condOffset= lexer.nextToken().getOffset(); + int condOffset= lexer.nextToken().getOffset(); condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); + int endOffset= lexer.currentToken().getEndOffset(); final char[] warning= lexer.getInputChars(condOffset, condEndOffset); final int id= type == IPreprocessorDirective.ppError ? IProblem.PREPROCESSOR_POUND_ERROR @@ -1059,17 +1045,20 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); break; default: - isProblem= true; - break; - } - - if (isProblem) { - int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, ident.getCharImage(), startOffset, endOffset); + break; } } - private void executeInclude(final Lexer lexer, int poundOffset, boolean include_next, boolean active) throws OffsetLimitReachedException { + private void executeInclude(final Lexer lexer, int poundOffset, boolean include_next, boolean active, boolean withinExpansion) throws OffsetLimitReachedException { + if (withinExpansion) { + final char[] name= lexer.currentToken().getCharImage(); + final int endOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, name, poundOffset, endOffset); + return; + } + lexer.setInsideIncludeDirective(true); final Token header= lexer.nextToken(); lexer.setInsideIncludeDirective(false); @@ -1228,14 +1217,15 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } - private void executeDefine(final Lexer lexer, int startOffset) throws OffsetLimitReachedException { + private void executeDefine(final Lexer lexer, int startOffset, boolean isActive) throws OffsetLimitReachedException { try { ObjectStyleMacro macrodef = fMacroDefinitionParser.parseMacroDefinition(lexer, this); - fMacroDictionary.put(macrodef.getNameCharArray(), macrodef); + if (isActive) + fMacroDictionary.put(macrodef.getNameCharArray(), macrodef); + final Token name= fMacroDefinitionParser.getNameToken(); - fLocationMap.encounterPoundDefine(startOffset, name.getOffset(), name.getEndOffset(), - macrodef.getExpansionOffset(), macrodef.getExpansionEndOffset(), macrodef); + macrodef.getExpansionOffset(), macrodef.getExpansionEndOffset(), isActive, macrodef); } catch (InvalidMacroDefinitionException e) { lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); handleProblem(IProblem.PREPROCESSOR_INVALID_MACRO_DEFN, e.fName, e.fStartOffset, e.fEndOffset); @@ -1260,63 +1250,108 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { fLocationMap.encounterPoundUndef(definition, startOffset, name.getOffset(), name.getEndOffset(), endOffset, namechars); } - private void executeIfdef(Lexer lexer, int startOffset, boolean positive, boolean withinExpansion) throws OffsetLimitReachedException { + private CodeState executeIfdef(Lexer lexer, int offset, boolean isIfndef, boolean withinExpansion) throws OffsetLimitReachedException { final Token name= lexer.nextToken(); - final int tt= name.getType(); - if (tt != IToken.tIDENTIFIER) { - if (tt == IToken.tCOMPLETION) { - throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, name); - } - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - handleProblem(IProblem.PREPROCESSOR_DEFINITION_NOT_FOUND, name.getCharImage(), startOffset, name.getEndOffset()); - return; - } lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + final int tt= name.getType(); + final int nameOffset = name.getOffset(); + final int nameEndOffset = name.getEndOffset(); final int endOffset= lexer.currentToken().getEndOffset(); - final char[] namechars= name.getCharImage(); - PreprocessorMacro macro= fMacroDictionary.get(namechars); - boolean isActive= (macro != null) == positive; - - fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - if (positive) { - fLocationMap.encounterPoundIfdef(startOffset, name.getOffset(), name.getEndOffset(), endOffset, isActive, macro); - } - else { - fLocationMap.encounterPoundIfndef(startOffset, name.getOffset(), name.getEndOffset(), endOffset, isActive, macro); - } - - if ((macro == null) == positive) { - skipOverConditionalCode(lexer, true, withinExpansion); - } + + boolean isActive= false; + PreprocessorMacro macro= null; + final Conditional conditional= fCurrentContext.newBranch(BranchKind.eIf, withinExpansion); + if (conditional.canHaveActiveBranch(withinExpansion)) { + // we need an identifier + if (tt != IToken.tIDENTIFIER) { + if (tt == IToken.tCOMPLETION) { + throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, name); + } + // report problem and treat as inactive + handleProblem(IProblem.PREPROCESSOR_DEFINITION_NOT_FOUND, name.getCharImage(), offset, nameEndOffset); + } else { + final char[] namechars= name.getCharImage(); + macro= fMacroDictionary.get(namechars); + isActive= (macro == null) == isIfndef; + } + } + + if (isIfndef) { + fLocationMap.encounterPoundIfndef(offset, nameOffset, nameEndOffset, endOffset, isActive, macro); + } else { + fLocationMap.encounterPoundIfdef(offset, nameOffset, nameEndOffset, endOffset, isActive, macro); + } + return fCurrentContext.setBranchState(conditional, isActive, withinExpansion); } - private void executeIf(Lexer lexer, int startOffset, boolean withinExpansion) throws OffsetLimitReachedException { - boolean isActive= false; - TokenList condition= new TokenList(); - final int condOffset= lexer.nextToken().getOffset(); - final int condEndOffset= getTokensWithinPPDirective(true, condition, withinExpansion); - final int endOffset= lexer.currentToken().getEndOffset(); - - fExpressionEvaluator.clearMacrosInDefinedExpression(); - if (condition.first() == null) { - handleProblem(IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, null, startOffset, endOffset); - } - else { - try { - isActive= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap); - } catch (EvalException e) { - handleProblem(e.getProblemID(), e.getProblemArg(), condOffset, endOffset); - } - } - - fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIf(startOffset, condOffset, condEndOffset, endOffset, isActive, fExpressionEvaluator.clearMacrosInDefinedExpression()); + private CodeState executeIf(Lexer lexer, int startOffset, boolean isElif, boolean withinExpansion) throws OffsetLimitReachedException { + Conditional cond= fCurrentContext.newBranch(isElif ? BranchKind.eElif : BranchKind.eIf, withinExpansion); + if (cond == null) { + char[] name= lexer.currentToken().getCharImage(); + int condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, condEndOffset); + return fCurrentContext.getCodeState(); + } - if (!isActive) { - skipOverConditionalCode(lexer, true, withinExpansion); - } + boolean isActive= false; + IASTName[] refs= IASTName.EMPTY_NAME_ARRAY; + int condOffset= lexer.nextToken().getOffset(); + int condEndOffset, endOffset; + + if (cond.canHaveActiveBranch(withinExpansion)) { + TokenList condition= new TokenList(); + condEndOffset= getTokensWithinPPDirective(true, condition, withinExpansion); + endOffset= lexer.currentToken().getEndOffset(); + + if (condition.first() == null) { + handleProblem(IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, null, startOffset, endOffset); + } else { + try { + fExpressionEvaluator.clearMacrosInDefinedExpression(); + isActive= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap); + refs = fExpressionEvaluator.clearMacrosInDefinedExpression(); + } catch (EvalException e) { + handleProblem(e.getProblemID(), e.getProblemArg(), condOffset, endOffset); + } + } + } else { + condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + endOffset= lexer.currentToken().getEndOffset(); + } + + if (isElif) { + fLocationMap.encounterPoundElif(startOffset, condOffset, condEndOffset, endOffset, isActive, refs); + } else { + fLocationMap.encounterPoundIf(startOffset, condOffset, condEndOffset, endOffset, isActive, refs); + } + return fCurrentContext.setBranchState(cond, isActive, withinExpansion); } + private CodeState executeElse(final Lexer lexer, final int startOffset,boolean withinExpansion) + throws OffsetLimitReachedException { + final int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + Conditional cond= fCurrentContext.newBranch(BranchKind.eElse, withinExpansion); + if (cond == null) { + handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, Keywords.cELSE, startOffset, endOffset); + return fCurrentContext.getCodeState(); + } + + final boolean isActive= cond.canHaveActiveBranch(withinExpansion); + fLocationMap.encounterPoundElse(startOffset, endOffset, isActive); + return fCurrentContext.setBranchState(cond, isActive, withinExpansion); + } + + private CodeState executeEndif(Lexer lexer, int startOffset, boolean withinExpansion) throws OffsetLimitReachedException { + final int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + final Conditional cond= fCurrentContext.newBranch(BranchKind.eEnd, withinExpansion); + if (cond == null) { + handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, Keywords.cENDIF, startOffset, endOffset); + } else { + fLocationMap.encounterPoundEndIf(startOffset, endOffset); + } + return fCurrentContext.getCodeState(); + } + /** * Runs the preprocessor on the rest of the line, storing the tokens in the holder supplied. * Macro expansion is reported to the location map. @@ -1326,6 +1361,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { */ private int getTokensWithinPPDirective(boolean isCondition, TokenList result, boolean withinExpansion) throws OffsetLimitReachedException { final ScannerContext scannerCtx= fCurrentContext; + scannerCtx.clearInactiveCodeMarkerToken(); int options= STOP_AT_NL; if (isCondition) options |= PROTECT_DEFINED; @@ -1357,135 +1393,69 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return scannerCtx.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); } - private void skipOverConditionalCode(final Lexer lexer, boolean takeElseBranch, boolean withinExpansion) throws OffsetLimitReachedException { - int nesting= 0; - while(true) { - final Token pound= lexer.nextDirective(); - int tt= pound.getType(); - if (tt != IToken.tPOUND) { - if (tt == IToken.tCOMPLETION) { - throw new OffsetLimitReachedException(ORIGIN_INACTIVE_CODE, pound); // completion in inactive code - } - return; - } - final Token ident= lexer.nextToken(); - tt= ident.getType(); - if (tt != IToken.tIDENTIFIER) { - if (tt == IToken.tCOMPLETION) { - throw new OffsetLimitReachedException(ORIGIN_INACTIVE_CODE, ident); // completion in inactive directive - } - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - continue; - } - - // we have an identifier - final char[] name = ident.getCharImage(); - final int type = fPPKeywords.get(name); - switch (type) { - case IPreprocessorDirective.ppImport: - case IPreprocessorDirective.ppInclude: - if (withinExpansion) { - int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, ident.getCharImage(), pound.getOffset(), endOffset); - } else { - executeInclude(lexer, ident.getOffset(), false, false); - } - break; - case IPreprocessorDirective.ppInclude_next: - if (withinExpansion) { - int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, ident.getCharImage(), pound.getOffset(), endOffset); - } else { - executeInclude(lexer, ident.getOffset(), true, false); - } - break; - case IPreprocessorDirective.ppIfdef: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - int endOffset= lexer.currentToken().getEndOffset(); - nesting++; - fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIfdef(pound.getOffset(), ident.getOffset(), ident.getEndOffset(), endOffset, false, null); - break; - case IPreprocessorDirective.ppIfndef: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); - nesting++; - fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIfndef(pound.getOffset(), ident.getOffset(), ident.getEndOffset(), endOffset, false, null); - break; - case IPreprocessorDirective.ppIf: - int condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); - nesting++; - fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIf(pound.getOffset(), ident.getOffset(), condEndOffset, endOffset, false, IASTName.EMPTY_NAME_ARRAY); - break; - case IPreprocessorDirective.ppElse: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELSE)) { - boolean isActive= nesting == 0 && takeElseBranch; - fLocationMap.encounterPoundElse(pound.getOffset(), ident.getEndOffset(), isActive); - if (isActive) { - return; - } - } - else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), ident.getEndOffset()); - } - break; - case IPreprocessorDirective.ppElif: - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELIF)) { - boolean isActive= false; - fExpressionEvaluator.clearMacrosInDefinedExpression(); - int condOffset= lexer.nextToken().getOffset(); - if (nesting == 0 && takeElseBranch) { - TokenList condition= new TokenList(); - condEndOffset= getTokensWithinPPDirective(true, condition, withinExpansion); - if (condition.first() != null) { - try { - isActive= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap); - } catch (EvalException e) { - handleProblem(e.getProblemID(), e.getProblemArg(), condOffset, condEndOffset); - } - } - } - else { - condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - } - endOffset= lexer.currentToken().getEndOffset(); - fCurrentContext.changeBranch(ScannerContext.BRANCH_ELIF); - fLocationMap.encounterPoundElif(pound.getOffset(), condOffset, condEndOffset, endOffset, isActive, fExpressionEvaluator.clearMacrosInDefinedExpression()); - - if (isActive) { - return; - } - } - else { - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), endOffset); - } - break; - case IPreprocessorDirective.ppEndif: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_END)) { - fLocationMap.encounterPoundEndIf(pound.getOffset(), ident.getEndOffset()); - if (nesting == 0) { - return; - } - --nesting; - } - else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), ident.getEndOffset()); - } - break; - default: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - break; - } - } - } - + private void skipOverConditionalCode(final Lexer lexer, boolean withinExpansion) throws OffsetLimitReachedException { + CodeState state= CodeState.eSkipInactive; + while (state == CodeState.eSkipInactive) { + state= skipBranch(lexer, withinExpansion); + } + } + + private CodeState skipBranch(final Lexer lexer, boolean withinExpansion) throws OffsetLimitReachedException { + while(true) { + final Token pound = lexer.nextDirective(); + int tt = pound.getType(); + if (tt != IToken.tPOUND) { + if (tt == IToken.tCOMPLETION) { + // completion in inactive code + throw new OffsetLimitReachedException(ORIGIN_INACTIVE_CODE, pound); + } + // must be the end of the lexer + return CodeState.eActive; + } + final Token ident = lexer.nextToken(); + tt = ident.getType(); + if (tt != IToken.tIDENTIFIER) { + if (tt == IToken.tCOMPLETION) { + // completion in inactive directive + throw new OffsetLimitReachedException(ORIGIN_INACTIVE_CODE, ident); + } + lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + continue; + } + + // we have an identifier + final char[] name = ident.getCharImage(); + final int type = fPPKeywords.get(name); + switch (type) { + case IPreprocessorDirective.ppImport: + case IPreprocessorDirective.ppInclude: + executeInclude(lexer, ident.getOffset(), false, false, withinExpansion); + break; + case IPreprocessorDirective.ppInclude_next: + executeInclude(lexer, ident.getOffset(), true, false, withinExpansion); + break; + case IPreprocessorDirective.ppDefine: + executeDefine(lexer, pound.getOffset(), false); + break; + case IPreprocessorDirective.ppIfdef: + return executeIfdef(lexer, pound.getOffset(), false, withinExpansion); + case IPreprocessorDirective.ppIfndef: + return executeIfdef(lexer, pound.getOffset(), true, withinExpansion); + case IPreprocessorDirective.ppIf: + return executeIf(lexer, pound.getOffset(), false, withinExpansion); + case IPreprocessorDirective.ppElif: + return executeIf(lexer, pound.getOffset(), true, withinExpansion); + case IPreprocessorDirective.ppElse: + return executeElse(lexer, pound.getOffset(), withinExpansion); + case IPreprocessorDirective.ppEndif: + return executeEndif(lexer, pound.getOffset(), withinExpansion); + default: + lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + break; + } + } + } + /** * The method assumes that the identifier is consumed. *
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java
index ea25fb2d703..639b1ee19af 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2009 Wind River Systems, Inc. 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
@@ -331,7 +331,7 @@ public class LocationMap implements ILocationResolver {
}
}
- public void encounterPoundDefine(int startOffset, int nameOffset, int nameEndOffset, int expansionOffset, int endOffset, IMacroBinding macrodef) {
+ public void encounterPoundDefine(int startOffset, int nameOffset, int nameEndOffset, int expansionOffset, int endOffset, boolean isActive, IMacroBinding macrodef) {
startOffset= getSequenceNumberForOffset(startOffset);
nameOffset= getSequenceNumberForOffset(nameOffset);
nameEndOffset= getSequenceNumberForOffset(nameEndOffset);
@@ -339,10 +339,10 @@ public class LocationMap implements ILocationResolver {
endOffset= getSequenceNumberForOffset(endOffset);
ASTPreprocessorNode astMacro;
if (!macrodef.isFunctionStyle()) {
- astMacro= new ASTMacroDefinition(fTranslationUnit, macrodef, startOffset, nameOffset, nameEndOffset, expansionOffset, endOffset);
+ astMacro= new ASTMacroDefinition(fTranslationUnit, macrodef, startOffset, nameOffset, nameEndOffset, expansionOffset, endOffset, isActive);
}
else {
- astMacro= new ASTFunctionStyleMacroDefinition(fTranslationUnit, macrodef, startOffset, nameOffset, nameEndOffset, expansionOffset, endOffset);
+ astMacro= new ASTFunctionStyleMacroDefinition(fTranslationUnit, macrodef, startOffset, nameOffset, nameEndOffset, expansionOffset, endOffset, isActive);
}
fDirectives.add(astMacro);
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java
index 71bd0559567..9f49ca4b776 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java
@@ -22,17 +22,28 @@ import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
final class ScannerContext {
private static final Token END_TOKEN = new Token(IToken.tEND_OF_INPUT, null, 0, 0);
- public static final Integer BRANCH_IF = new Integer(0);
- public static final Integer BRANCH_ELIF = new Integer(1);
- public static final Integer BRANCH_ELSE = new Integer(2);
- public static final Integer BRANCH_END = new Integer(3);
+ enum BranchKind {eIf, eElif, eElse, eEnd}
+ enum CodeState {eActive, eParseInactive, eSkipInactive}
+ final static class Conditional {
+ private CodeState fInitialState;
+ private BranchKind fLast;
+ private boolean fTakeElse= true;
+ Conditional(CodeState state) {
+ fInitialState= state;
+ fLast= BranchKind.eIf;
+ }
+ boolean canHaveActiveBranch(boolean withinExpansion) {
+ return fTakeElse && (fInitialState == CodeState.eActive || withinExpansion);
+ }
+ }
+ private CodeState fInactiveState= CodeState.eSkipInactive;
private final ILocationCtx fLocationCtx;
private final ScannerContext fParent;
private final Lexer fLexer;
- private ArrayListnull
,
+ * if the change is not legal at this point.
*/
- public final boolean changeBranch(Integer branchKind) {
- if (fBranches == null) {
- fBranches= new ArrayList