Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Schorn2007-11-02 11:40:32 -0400
committerMarkus Schorn2007-11-02 11:40:32 -0400
commit9527ea7033e58200c1f231281d7ba6eabdcbb50b (patch)
tree6bc0d1791625c2196f5122dfd0cc3ad44c2f320d
parent6141cbb61dacead7bbec1066c6e4038bb4621e8b (diff)
downloadorg.eclipse.cdt-9527ea7033e58200c1f231281d7ba6eabdcbb50b.tar.gz
org.eclipse.cdt-9527ea7033e58200c1f231281d7ba6eabdcbb50b.tar.xz
org.eclipse.cdt-9527ea7033e58200c1f231281d7ba6eabdcbb50b.zip
More testcases and fixes for the preprocessor.
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LexerTests.java70
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java18
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PortedScannerTests.java3
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java91
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java4
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java41
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java55
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java10
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java61
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java55
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroDefinitionParser.java22
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java275
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java8
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenList.java35
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java1
15 files changed, 500 insertions, 249 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LexerTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LexerTests.java
index 08c321be868..a9e57958cb2 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LexerTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LexerTests.java
@@ -277,7 +277,25 @@ public class LexerTests extends BaseTestCase {
id("a");
eof();
}
-
+
+ public void testMinimalComment() throws Exception {
+ init("a/**/b/**/");
+ id("a");
+ comment("/**/");
+ id("b");
+ comment("/**/");
+ eof();
+ init("a//\nb//\r\nc");
+ id("a");
+ comment("//");
+ nl();
+ id("b");
+ comment("//");
+ nl();
+ id("c");
+ eof();
+ }
+
public void testHeaderName() throws Exception {
init("p\"'/*//\\\"");
fLexer.setInsideIncludeDirective(true);
@@ -316,7 +334,7 @@ public class LexerTests extends BaseTestCase {
init(ident, false, true);
final int idxDollar = ident.indexOf('$');
id(ident.substring(0, idxDollar));
- token(IToken.tOTHER_CHARACTER, "$");
+ token(Lexer.tOTHER_CHARACTER, "$");
id(ident.substring(idxDollar+1));
}
@@ -430,13 +448,13 @@ public class LexerTests extends BaseTestCase {
IToken.tLBRACE, IToken.tRBRACE, IToken.tPOUNDPOUND, IToken.tPOUND, IToken.tSEMI,
IToken.tCOLON, IToken.tELLIPSIS, IToken.tQUESTION, IToken.tDOT, IToken.tCOLONCOLON, IToken.tDOT,
IToken.tDOTSTAR, IToken.tPLUS, IToken.tMINUS, IToken.tSTAR, IToken.tDIV, IToken.tMOD,
- IToken.tXOR, IToken.tAMPER, IToken.tBITOR, IToken.tCOMPL, IToken.tASSIGN, IToken.tNOT,
+ IToken.tXOR, IToken.tAMPER, IToken.tBITOR, IToken.tBITCOMPLEMENT, IToken.tASSIGN, IToken.tNOT,
IToken.tLT, IToken.tGT, IToken.tPLUSASSIGN, IToken.tMINUSASSIGN, IToken.tSTARASSIGN,
IToken.tDIVASSIGN, IToken.tMODASSIGN, IToken.tXORASSIGN, IToken.tAMPERASSIGN,
IToken.tBITORASSIGN, IToken.tSHIFTL, IToken.tSHIFTR, IToken.tSHIFTLASSIGN,
IToken.tSHIFTRASSIGN, IToken.tEQUAL, IToken.tNOTEQUAL, IToken.tLTEQUAL, IToken.tGTEQUAL,
IToken.tAND, IToken.tOR, IToken.tINCR, IToken.tDECR, IToken.tCOMMA, IToken.tARROWSTAR,
- IToken.tARROW, IGCCToken.tMIN, IGCCToken.tMAX, IToken.tOTHER_CHARACTER,
+ IToken.tARROW, IGCCToken.tMIN, IGCCToken.tMAX, Lexer.tOTHER_CHARACTER,
};
for (int splices=0; splices<9; splices++) {
@@ -543,4 +561,48 @@ public class LexerTests extends BaseTestCase {
token(IToken.tOR);
eof();
}
+
+ public void testNextDirective() throws Exception {
+ init("#if \n /*\n#*/ \"#\" '#' \\\n# ??/\n# \n## \n#\\\n# \n#??/\n# \n#ok \r\n#");
+ token(IToken.tPOUND);
+ id("if");
+ fLexer.consumeLine(0);
+ assertEquals(Lexer.tNEWLINE, fLexer.currentToken().getType());
+ fLexer.nextDirective();
+ comment("/*\n#*/");
+ token(IToken.tPOUND);
+ id("ok");
+ fLexer.nextDirective();
+ ws();
+ token(IToken.tPOUND);
+ eof();
+
+ init("#if \n??=??= \n#??= \n??=# \n??=\\\n??= \n#\\\n??= \n??=\\\n# \n??=ok \n??=");
+ token(IToken.tPOUND);
+ id("if");
+ fLexer.consumeLine(0);
+ assertEquals(Lexer.tNEWLINE, fLexer.currentToken().getType());
+ fLexer.nextDirective();
+ ws();
+ token(IToken.tPOUND);
+ id("ok");
+ fLexer.nextDirective();
+ ws();
+ token(IToken.tPOUND);
+ eof();
+
+ init("#if \n%:%: \n%:\\\n%: \n%:??/\n%: \n%:ok \n%:");
+ token(IToken.tPOUND);
+ id("if");
+ fLexer.consumeLine(0);
+ assertEquals(Lexer.tNEWLINE, fLexer.currentToken().getType());
+ fLexer.nextDirective();
+ ws();
+ token(IToken.tPOUND);
+ id("ok");
+ fLexer.nextDirective();
+ ws();
+ token(IToken.tPOUND);
+ eof();
+ }
}
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 6383005cbd1..8aaf2482aa7 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
@@ -299,7 +299,7 @@ public class LocationMapTests extends BaseTestCase {
IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements();
assertEquals(2, prep.length);
checkError(prep[0], "", "",FN,0,0,1);
- checkError(prep[1], new String(DIGITS), "12", FN,0,16,1);
+ checkError(prep[1], "012", "12", FN,0,3,1);
}
public void testPragma() {
@@ -309,7 +309,7 @@ public class LocationMapTests extends BaseTestCase {
IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements();
assertEquals(2, prep.length);
checkPragma(prep[0], "", "", FN,0,0,1);
- checkPragma(prep[1], new String(DIGITS), "12", FN,0,16,1);
+ checkPragma(prep[1], "012", "12", FN,0,3,1);
}
public void testIncludes() {
@@ -319,7 +319,7 @@ public class LocationMapTests extends BaseTestCase {
IASTPreprocessorIncludeStatement[] includes= fLocationMap.getIncludeDirectives();
assertEquals(2, includes.length);
checkInclude(includes[0], "", "", "n1", "", true, false, FN, 0, 0, 1, 0, 0);
- checkInclude(includes[1], new String(DIGITS), "12", "n2", "f2", false, true, FN, 0, 16, 1, 1, 2);
+ checkInclude(includes[1], "012", "12", "n2", "f2", false, true, FN, 0, 3, 1, 1, 2);
}
public void testIf() {
@@ -329,7 +329,7 @@ public class LocationMapTests extends BaseTestCase {
IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements();
assertEquals(2, prep.length);
checkIf(prep[0], "", "", false, FN, 0, 0, 1);
- checkIf(prep[1], new String(DIGITS), "12", true, FN, 0, 16, 1);
+ checkIf(prep[1], "012", "12", true, FN, 0, 3, 1);
}
public void testIfdef() {
@@ -339,7 +339,7 @@ public class LocationMapTests extends BaseTestCase {
IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements();
assertEquals(2, prep.length);
checkIfdef(prep[0], "", "", false, FN, 0, 0, 1);
- checkIfdef(prep[1], new String(DIGITS), "12", true, FN, 0, 16, 1);
+ checkIfdef(prep[1], "012", "12", true, FN, 0, 3, 1);
}
public void testIfndef() {
@@ -349,7 +349,7 @@ public class LocationMapTests extends BaseTestCase {
IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements();
assertEquals(2, prep.length);
checkIfndef(prep[0], "", "", false, FN, 0, 0, 1);
- checkIfndef(prep[1], new String(DIGITS), "12", true, FN, 0, 16, 1);
+ checkIfndef(prep[1], "012", "12", true, FN, 0, 3, 1);
}
public void testElif() {
@@ -359,7 +359,7 @@ public class LocationMapTests extends BaseTestCase {
IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements();
assertEquals(2, prep.length);
checkElif(prep[0], "", "", false, FN, 0, 0, 1);
- checkElif(prep[1], new String(DIGITS), "12", true, FN, 0, 16, 1);
+ checkElif(prep[1], "012", "12", true, FN, 0, 3, 1);
}
public void testElse() {
@@ -430,7 +430,7 @@ public class LocationMapTests extends BaseTestCase {
IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements();
assertEquals(2, prep.length);
checkMacroUndef(prep[0], null, "", "n1", "", FN, 0, 0, 1, 0, 0);
- checkMacroUndef(prep[1], macro1, new String(DIGITS), "n2", "3456", FN, 0, 16, 1, 3, 4);
+ checkMacroUndef(prep[1], macro1, "0123456", "n2", "3456", FN, 0, 7, 1, 3, 4);
}
public void testMacroExpansion() {
@@ -551,7 +551,7 @@ public class LocationMapTests extends BaseTestCase {
inclusions= inclusions[0].getNestedInclusions();
assertEquals(1, inclusions.length);
- checkInclude(inclusions[0].getIncludeDirective(), "b4b", "4", "pre11", "pre11", false, true, "pre1", 6, 3, 1, 7, 1);
+ checkInclude(inclusions[0].getIncludeDirective(), "b4", "4", "pre11", "pre11", false, true, "pre1", 6, 2, 1, 7, 1);
assertEquals(0, inclusions[0].getNestedInclusions().length);
}
}
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PortedScannerTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PortedScannerTests.java
index 34270107c07..4dcafbb8611 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PortedScannerTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PortedScannerTests.java
@@ -1763,7 +1763,7 @@ public class PortedScannerTests extends PreprocessorTestsBase {
initializeScanner(writer.toString());
fullyTokenize();
IASTProblem[] problems= fLocationResolver.getScannerProblems();
- assertEquals(16, problems.length);
+ assertEquals(17, problems.length);
int i= 0;
assertEquals(IProblem.SCANNER_BAD_OCTAL_FORMAT, problems[i].getID() );
assertEquals(IProblem.SCANNER_BAD_DECIMAL_FORMAT, problems[++i].getID() );
@@ -1775,6 +1775,7 @@ public class PortedScannerTests extends PreprocessorTestsBase {
assertEquals(IProblem.SCANNER_ILLEGAL_IDENTIFIER, problems[++i].getID() );
assertEquals(IProblem.SCANNER_BAD_CONDITIONAL_EXPRESSION,problems[++i].getID() );
assertEquals(IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, problems[++i].getID() );
+ assertEquals(IProblem.SCANNER_BAD_CHARACTER, problems[++i].getID() );
assertEquals(IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, problems[++i].getID() );
assertEquals(IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, problems[++i].getID() );
assertEquals(IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, problems[++i].getID() );
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java
index 5ad102008f8..685a5f81146 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java
@@ -345,6 +345,7 @@ public class PreprocessorTests extends PreprocessorTestsBase {
validateEOF();
validateProblemCount(0);
}
+
// #define OBJ __VA_ARGS__
// #define func(x) __VA_ARGS__
// OBJ;
@@ -398,4 +399,94 @@ public class PreprocessorTests extends PreprocessorTestsBase {
validateEOF();
validateProblemCount(0);
}
+
+ // #define ONE(a, ...) int x
+ // #define TWO(b, args...) int y
+ // ONE("string");
+ // TWO("string");
+ public void testSkippingVarags() throws Exception {
+ initializeScanner();
+ validateToken(IToken.t_int);
+ validateIdentifier("x");
+ validateToken(IToken.tSEMI);
+
+ validateToken(IToken.t_int);
+ validateIdentifier("y");
+ validateToken(IToken.tSEMI);
+
+ validateEOF();
+ validateProblemCount(0);
+ }
+
+ // #define eval(f,x) f(x)
+ // #define m(x) m[x]
+ // eval(m,y);
+ public void testReconsiderArgsForExpansion() throws Exception {
+ initializeScanner();
+ validateIdentifier("m");
+ validateToken(IToken.tLBRACKET);
+ validateIdentifier("y");
+ validateToken(IToken.tRBRACKET);
+ validateToken(IToken.tSEMI);
+
+ validateEOF();
+ validateProblemCount(0);
+ }
+
+ //#define f\
+ //(x) ok
+ // f(x)
+ public void testLineSpliceInMacroDefinition() throws Exception {
+ initializeScanner();
+ validateIdentifier("ok");
+ validateEOF();
+ validateProblemCount(0);
+ }
+
+ // #define f() fval
+ // #define nospace f()f()
+ // #define space f() f()
+ // #define str(x) #x
+ // #define xstr(x) str(x)
+ // #define tp1(x,y,z) [x ## y ## z]
+ // #define tp2(x,y,z) [ x ## y ## z ]
+ // #define tstr1(x,y) [#x#y]
+ // #define tstr2(x,y) [ #x #y ]
+ // xstr(nospace);
+ // xstr(space);
+ // xstr(tp1(a b, c d , e f));
+ // xstr(tp2(a b, c d , e f));
+ // xstr(tp1(a-b, c-d , e-f));
+ // xstr(tp2(a-b, c-d , e-f));
+ // xstr(tstr1(a b, c d));
+ // xstr(tstr2(a b, c d));
+ public void testSpaceInStringify() throws Exception {
+ initializeScanner();
+ validateString("fvalfval");
+ validateToken(IToken.tSEMI);
+
+ validateString("fval fval");
+ validateToken(IToken.tSEMI);
+
+ validateString("[a bc de f]");
+ validateToken(IToken.tSEMI);
+
+ validateString("[ a bc de f ]");
+ validateToken(IToken.tSEMI);
+
+ validateString("[a-bc-de-f]");
+ validateToken(IToken.tSEMI);
+
+ validateString("[ a-bc-de-f ]");
+ validateToken(IToken.tSEMI);
+
+ validateString("[\\\"a b\\\"\\\"c d\\\"]");
+ validateToken(IToken.tSEMI);
+
+ validateString("[ \\\"a b\\\" \\\"c d\\\" ]");
+ validateToken(IToken.tSEMI);
+
+ validateEOF();
+ validateProblemCount(0);
+ }
}
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 7c44405dbde..25b2a23c020 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
@@ -6,7 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * IBM Rational Software - Initial API and implementation
+ * IBM Rational Software - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.parser;
@@ -118,7 +119,6 @@ public interface IToken {
static public final int tDOT = 50;
static public final int tDIVASSIGN = 51;
static public final int tDIV = 52;
- static public final int tOTHER_CHARACTER= 53;
/** @deprecated use {@link #tAND} */
static public final int t_and = 54;
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 88dfa75750f..db8ec1022ac 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
@@ -29,6 +29,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorObjectStyleMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorPragmaStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorUndefStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
@@ -125,12 +126,10 @@ class ASTComment extends ASTPreprocessorNode implements IASTComment {
abstract class ASTDirectiveWithCondition extends ASTPreprocessorNode {
private final int fConditionOffset;
- private final int fConditionLength;
private final boolean fActive;
- public ASTDirectiveWithCondition(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, int endNumber, boolean active) {
+ public ASTDirectiveWithCondition(IASTTranslationUnit parent, int startNumber, int condNumber, int endNumber, boolean active) {
super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber);
fConditionOffset= condNumber;
- fConditionLength= condEndNumber-condNumber;
fActive= active;
}
@@ -139,7 +138,7 @@ abstract class ASTDirectiveWithCondition extends ASTPreprocessorNode {
}
public String getConditionString() {
- return getSource(fConditionOffset, fConditionLength);
+ return getSource(fConditionOffset, getOffset() + getLength() - fConditionOffset);
}
public char[] getCondition() {
@@ -154,8 +153,8 @@ class ASTEndif extends ASTPreprocessorNode implements IASTPreprocessorEndifState
}
class ASTElif extends ASTDirectiveWithCondition implements IASTPreprocessorElifStatement {
- public ASTElif(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, int endNumber, boolean active) {
- super(parent, startNumber, condNumber, condEndNumber, endNumber, active);
+ public ASTElif(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, boolean active) {
+ super(parent, startNumber, condNumber, condEndNumber, active);
}
}
@@ -171,26 +170,26 @@ class ASTElse extends ASTPreprocessorNode implements IASTPreprocessorElseStateme
}
class ASTIfndef extends ASTDirectiveWithCondition implements IASTPreprocessorIfndefStatement {
- public ASTIfndef(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, int endNumber, boolean active) {
- super(parent, startNumber, condNumber, condEndNumber, endNumber, active);
+ public ASTIfndef(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, boolean active) {
+ super(parent, startNumber, condNumber, condEndNumber, active);
}
}
class ASTIfdef extends ASTDirectiveWithCondition implements IASTPreprocessorIfdefStatement {
- public ASTIfdef(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, int endNumber, boolean active) {
- super(parent, startNumber, condNumber, condEndNumber, endNumber, active);
+ public ASTIfdef(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, boolean active) {
+ super(parent, startNumber, condNumber, condEndNumber, active);
}
}
class ASTIf extends ASTDirectiveWithCondition implements IASTPreprocessorIfStatement {
- public ASTIf(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, int endNumber, boolean active) {
- super(parent, startNumber, condNumber, condEndNumber, endNumber, active);
+ public ASTIf(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, boolean active) {
+ super(parent, startNumber, condNumber, condEndNumber, active);
}
}
class ASTError extends ASTDirectiveWithCondition implements IASTPreprocessorErrorStatement {
- public ASTError(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, int endNumber) {
- super(parent, startNumber, condNumber, condEndNumber, endNumber, true);
+ public ASTError(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber) {
+ super(parent, startNumber, condNumber, condEndNumber, true);
}
public char[] getMessage() {
@@ -199,8 +198,8 @@ class ASTError extends ASTDirectiveWithCondition implements IASTPreprocessorErro
}
class ASTPragma extends ASTDirectiveWithCondition implements IASTPreprocessorPragmaStatement {
- public ASTPragma(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, int endNumber) {
- super(parent, startNumber, condNumber, condEndNumber, endNumber, true);
+ public ASTPragma(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber) {
+ super(parent, startNumber, condNumber, condEndNumber, true);
}
public char[] getMessage() {
@@ -215,9 +214,9 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
private final boolean fIsResolved;
private final boolean fIsSystemInclude;
- public ASTInclusionStatement(IASTTranslationUnit parent, int startNumber, int nameStartNumber, int nameEndNumber, int endNumber,
+ public ASTInclusionStatement(IASTTranslationUnit parent, int startNumber, int nameStartNumber, int nameEndNumber,
char[] headerName, String filePath, boolean userInclude, boolean active) {
- super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber);
+ super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, nameEndNumber);
fName= new ASTPreprocessorName(this, IASTPreprocessorIncludeStatement.INCLUDE_NAME, nameStartNumber, nameEndNumber, headerName, null);
fPath= filePath == null ? "" : filePath; //$NON-NLS-1$
fIsActive= active;
@@ -246,7 +245,7 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
}
}
-class ASTMacro extends ASTPreprocessorNode implements IASTPreprocessorMacroDefinition {
+class ASTMacro extends ASTPreprocessorNode implements IASTPreprocessorObjectStyleMacroDefinition {
private final ASTPreprocessorName fName;
/**
@@ -335,8 +334,8 @@ class ASTFunctionMacro extends ASTMacro implements IASTPreprocessorFunctionStyle
class ASTUndef extends ASTPreprocessorNode implements IASTPreprocessorUndefStatement {
private final IASTName fName;
- public ASTUndef(IASTTranslationUnit parent, char[] name, int startNumber, int nameNumber, int nameEndNumber, int endNumber, IBinding binding) {
- super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber);
+ public ASTUndef(IASTTranslationUnit parent, char[] name, int startNumber, int nameNumber, int nameEndNumber, IBinding binding) {
+ super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, nameEndNumber);
fName= new ASTPreprocessorName(this, IASTPreprocessorUndefStatement.MACRO_NAME, nameNumber, nameEndNumber, name, binding);
}
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 34bb9e620de..abcb5392832 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
@@ -51,13 +51,24 @@ import org.eclipse.cdt.internal.core.parser.scanner2.ScannerUtility;
* you should be using the {@link IScanner} interface.
* @since 5.0
*/
+/**
+ * @since 5.0
+ *
+ */
+/**
+ * @since 5.0
+ *
+ */
public class CPreprocessor implements ILexerLog, IScanner {
+ public static final String PROP_VALUE = "CPreprocessor"; //$NON-NLS-1$
+
public static final int tDEFINED= IToken.FIRST_RESERVED_PREPROCESSOR;
public static final int tEXPANDED_IDENTIFIER= IToken.FIRST_RESERVED_PREPROCESSOR+1;
public static final int tSCOPE_MARKER= IToken.FIRST_RESERVED_PREPROCESSOR+2;
public static final int tSPACE= IToken.FIRST_RESERVED_PREPROCESSOR+3;
- public static final int tMACRO_PARAMETER= IToken.FIRST_RESERVED_PREPROCESSOR+4;
- public static final int tEMPTY_TOKEN = IToken.FIRST_RESERVED_PREPROCESSOR+5;
+ public static final int tNOSPACE= IToken.FIRST_RESERVED_PREPROCESSOR+4;
+ public static final int tMACRO_PARAMETER= IToken.FIRST_RESERVED_PREPROCESSOR+5;
+ public static final int tEMPTY_TOKEN = IToken.FIRST_RESERVED_PREPROCESSOR+6;
@@ -418,9 +429,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
Token t1= fPrefetchedToken;
if (t1 == null) {
t1= fetchTokenFromPreprocessor();
- final int offset= fLocationMap.getSequenceNumberForOffset(t1.getOffset());
- final int endOffset= fLocationMap.getSequenceNumberForOffset(t1.getEndOffset());
- t1.setOffset(offset, endOffset);
+ adjustOffsets(t1);
}
else {
fPrefetchedToken= null;
@@ -442,6 +451,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
int endOffset= 0;
loop: while(true) {
t2= fetchTokenFromPreprocessor();
+ adjustOffsets(t2);
final int tt2= t2.getType();
switch(tt2) {
case IToken.tLSTRING:
@@ -481,6 +491,13 @@ public class CPreprocessor implements ILexerLog, IScanner {
return t1;
}
+ private void adjustOffsets(Token t1) {
+ final int offset= fLocationMap.getSequenceNumberForOffset(t1.getOffset());
+ final int endOffset= fLocationMap.getSequenceNumberForOffset(t1.getEndOffset());
+ t1.setOffset(offset, endOffset);
+ t1.setNext(null);
+ }
+
private void appendStringContent(StringBuffer buf, Token t1) {
final char[] image= t1.getCharImage();
final int start= image[0]=='"' ? 1 : 2;
@@ -509,6 +526,15 @@ public class CPreprocessor implements ILexerLog, IScanner {
ppToken= fCurrentContext.nextPPToken();
continue;
+ case Lexer.tOTHER_CHARACTER:
+ if (!fExpandingMacro) {
+ handleProblem(IProblem.SCANNER_BAD_CHARACTER, ppToken.getCharImage(),
+ ppToken.getOffset(), ppToken.getEndOffset());
+ ppToken= fCurrentContext.nextPPToken();
+ continue;
+ }
+ break;
+
case Lexer.tEND_OF_INPUT:
final ILocationCtx locationCtx = fCurrentContext.getLocationCtx();
if (locationCtx != null) {
@@ -549,7 +575,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
return ppToken;
case IToken.tINTEGER:
- if (fCheckNumbers) {
+ if (fCheckNumbers && !fExpandingMacro) {
checkNumber(ppToken, false);
}
break;
@@ -878,7 +904,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
endOffset= lexer.currentToken().getEndOffset();
if (fCurrentContext.changeBranch(ScannerContext.BRANCH_END)) {
- fLocationMap.encounterPoundEndIf(startOffset, endOffset);
+ fLocationMap.encounterPoundEndIf(startOffset, condEndOffset);
}
else {
handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, endOffset);
@@ -889,11 +915,11 @@ public class CPreprocessor implements ILexerLog, IScanner {
condOffset= lexer.nextToken().getOffset();
condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
endOffset= lexer.currentToken().getEndOffset();
- final char[] warning= lexer.getInputChars(condOffset, endOffset);
+ final char[] warning= lexer.getInputChars(condOffset, condEndOffset);
final int id= type == IPreprocessorDirective.ppError
? IProblem.PREPROCESSOR_POUND_ERROR
: IProblem.PREPROCESSOR_POUND_WARNING;
- handleProblem(id, warning, startOffset, endOffset);
+ handleProblem(id, warning, condOffset, condEndOffset);
fLocationMap.encounterPoundError(startOffset, condOffset, condEndOffset, endOffset);
break;
case IPreprocessorDirective.ppPragma:
@@ -1050,12 +1076,12 @@ public class CPreprocessor implements ILexerLog, IScanner {
ObjectStyleMacro macrodef = fMacroDefinitionParser.parseMacroDefinition(lexer, this);
fMacroDictionary.put(macrodef.getNameCharArray(), macrodef);
final Token name= fMacroDefinitionParser.getNameToken();
- final int endOffset= lexer.currentToken().getEndOffset();
+
fLocationMap.encounterPoundDefine(startOffset, name.getOffset(), name.getEndOffset(),
- fMacroDefinitionParser.getExpansionOffset(), endOffset, macrodef);
+ macrodef.getExpansionOffset(), macrodef.getExpansionEndOffset(), macrodef);
} catch (InvalidMacroDefinitionException e) {
- int end= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
- handleProblem(IProblem.PREPROCESSOR_INVALID_MACRO_DEFN, e.fName, startOffset, end);
+ lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
+ handleProblem(IProblem.PREPROCESSOR_INVALID_MACRO_DEFN, e.fName, e.fStartOffset, e.fEndOffset);
}
}
@@ -1349,10 +1375,9 @@ public class CPreprocessor implements ILexerLog, IScanner {
throw new UnsupportedOperationException();
}
public org.eclipse.cdt.internal.core.parser.scanner2.ILocationResolver getLocationResolver() {
- throw new UnsupportedOperationException();
+ return fLocationMap;
}
public void setOffsetBoundary(int offset) {
throw new UnsupportedOperationException();
}
-
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java
index 0e5f29dc643..d9ab68aca86 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java
@@ -6,11 +6,12 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * IBM - Initial API and implementation
- * Markus Schorn (Wind River Systems)
+ * IBM - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
+import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
@@ -83,4 +84,9 @@ public interface ILocationResolver extends org.eclipse.cdt.internal.core.parser.
* Returns the definition for a macro.
*/
public IASTName[] getDeclarations(IMacroBinding binding);
+
+ /**
+ * Returns the comments encountered.
+ */
+ IASTComment[] getComments();
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java
index 792ecdf66cd..758e55d04cd 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java
@@ -41,6 +41,7 @@ final public class Lexer {
public static final int tEND_OF_INPUT = IToken.FIRST_RESERVED_SCANNER + 2;
public static final int tQUOTE_HEADER_NAME = IToken.FIRST_RESERVED_SCANNER + 3;
public static final int tSYSTEM_HEADER_NAME = IToken.FIRST_RESERVED_SCANNER + 4;
+ public static final int tOTHER_CHARACTER = IToken.FIRST_RESERVED_SCANNER + 5;
private static final int END_OF_INPUT = -1;
private static final int ORIGIN_LEXER = OffsetLimitReachedException.ORIGIN_LEXER;
@@ -176,33 +177,6 @@ final public class Lexer {
}
}
- /**
- * Advances to the next newline.
- * @return the list of tokens found on this line.
- * @param origin parameter for the {@link OffsetLimitReachedException} when it has to be thrown.
- */
- public final void getTokensOfLine(int origin, TokenList result) throws OffsetLimitReachedException {
- Token t= fToken;
- while(true) {
- switch(t.getType()) {
- case IToken.tCOMPLETION:
- fToken= t;
- throw new OffsetLimitReachedException(origin, t);
- case Lexer.tEND_OF_INPUT:
- fToken= t;
- if (fOptions.fSupportContentAssist) {
- throw new OffsetLimitReachedException(origin, null);
- }
- return;
- case Lexer.tNEWLINE:
- fToken= t;
- return;
- }
- result.append(t);
- t= fetchToken();
- }
- }
-
/**
* Advances to the next pound token that starts a preprocessor directive.
* @return pound token of the directive or end-of-input.
@@ -273,18 +247,34 @@ final public class Lexer {
lineComment(start);
continue;
case '*':
- nextCharPhase3();
blockComment(start);
continue;
}
continue;
+
+ case '%':
+ if (hadNL) {
+ if (d == ':') {
+ // found at least '#'
+ final int e= nextCharPhase3();
+ if (e == '%') {
+ markPhase3();
+ if (nextCharPhase3() == ':') {
+ // found '##'
+ nextCharPhase3();
+ continue;
+ }
+ restorePhase3();
+ }
+ fFirstTokenAfterNewline= true;
+ fToken= newDigraphToken(IToken.tPOUND, start);
+ return fToken;
+ }
+ }
+ continue;
case '#':
- if (d == '#') {
- nextCharPhase3();
- continue;
- }
- if (hadNL) {
+ if (hadNL && d != '#') {
fFirstTokenAfterNewline= true;
fToken= newToken(IToken.tPOUND, start);
return fToken;
@@ -359,7 +349,7 @@ final public class Lexer {
nextCharPhase3();
return identifier(start, 2);
}
- return newToken(IToken.tOTHER_CHARACTER, start, 1);
+ return newToken(tOTHER_CHARACTER, start, 1);
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
@@ -470,7 +460,6 @@ final public class Lexer {
lineComment(start);
continue;
case '*':
- nextCharPhase3();
blockComment(start);
continue;
}
@@ -607,7 +596,7 @@ final public class Lexer {
break;
}
// handles for instance @
- return newToken(IToken.tOTHER_CHARACTER, start, 1);
+ return newToken(tOTHER_CHARACTER, start, 1);
}
}
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 fd72c14c28f..7891c7c92b3 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
@@ -118,7 +118,7 @@ public class LocationMap implements ILocationResolver {
int nameEndNumber= getSequenceNumberForOffset(nameEndOffset);
int endNumber= getSequenceNumberForOffset(endOffset);
final ASTInclusionStatement inclusionStatement=
- new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, endNumber, name, filename, userInclude, true);
+ new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, name, filename, userInclude, true);
fDirectives.add(inclusionStatement);
fCurrentContext= new FileLocationCtx((ContainerLocationCtx) fCurrentContext, filename, buffer, startOffset, endOffset, endNumber, inclusionStatement);
fLastChildInsertionOffset= 0;
@@ -203,11 +203,11 @@ public class LocationMap implements ILocationResolver {
*/
public void encounterPoundInclude(int startOffset, int nameOffset, int nameEndOffset, int endOffset,
char[] name, String filename, boolean userInclude, boolean active) {
- startOffset= getSequenceNumberForOffset(startOffset); // there may be a macro expansion
- nameOffset= getSequenceNumberForOffset(nameOffset); // there may be a macro expansion
+ startOffset= getSequenceNumberForOffset(startOffset);
+ nameOffset= getSequenceNumberForOffset(nameOffset);
nameEndOffset= getSequenceNumberForOffset(nameEndOffset);
- endOffset= getSequenceNumberForOffset(endOffset);
- fDirectives.add(new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset, nameEndOffset, endOffset, name, filename, userInclude, active));
+// endOffset= getSequenceNumberForOffset(endOffset);
+ fDirectives.add(new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset, nameEndOffset, name, filename, userInclude, active));
}
public void encounteredComment(int offset, int endOffset, boolean isBlockComment) {
@@ -230,11 +230,11 @@ public class LocationMap implements ILocationResolver {
}
public void encounterPoundElif(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean isActive) {
- startOffset= getSequenceNumberForOffset(startOffset); // there may be a macro expansion
- condOffset= getSequenceNumberForOffset(condOffset); // there may be a macro expansion
+ startOffset= getSequenceNumberForOffset(startOffset);
+ condOffset= getSequenceNumberForOffset(condOffset);
condEndOffset= getSequenceNumberForOffset(condEndOffset);
- endOffset= getSequenceNumberForOffset(endOffset);
- fDirectives.add(new ASTElif(fTranslationUnit, startOffset, condOffset, condEndOffset, endOffset, isActive));
+ // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
+ fDirectives.add(new ASTElif(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive));
}
public void encounterPoundEndIf(int startOffset, int endOffset) {
@@ -247,40 +247,40 @@ public class LocationMap implements ILocationResolver {
startOffset= getSequenceNumberForOffset(startOffset);
condOffset= getSequenceNumberForOffset(condOffset);
condEndOffset= getSequenceNumberForOffset(condEndOffset);
- endOffset= getSequenceNumberForOffset(endOffset);
- fDirectives.add(new ASTError(fTranslationUnit, startOffset, condOffset, condEndOffset, endOffset));
+ // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
+ fDirectives.add(new ASTError(fTranslationUnit, startOffset, condOffset, condEndOffset));
}
public void encounterPoundPragma(int startOffset, int condOffset, int condEndOffset, int endOffset) {
startOffset= getSequenceNumberForOffset(startOffset);
condOffset= getSequenceNumberForOffset(condOffset);
condEndOffset= getSequenceNumberForOffset(condEndOffset);
- endOffset= getSequenceNumberForOffset(endOffset);
- fDirectives.add(new ASTPragma(fTranslationUnit, startOffset, condOffset, condEndOffset, endOffset));
+ // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
+ fDirectives.add(new ASTPragma(fTranslationUnit, startOffset, condOffset, condEndOffset));
}
public void encounterPoundIfdef(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean isActive) {
startOffset= getSequenceNumberForOffset(startOffset);
condOffset= getSequenceNumberForOffset(condOffset);
condEndOffset= getSequenceNumberForOffset(condEndOffset);
- endOffset= getSequenceNumberForOffset(endOffset);
- fDirectives.add(new ASTIfdef(fTranslationUnit, startOffset, condOffset, condEndOffset, endOffset, isActive));
+ // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
+ fDirectives.add(new ASTIfdef(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive));
}
public void encounterPoundIfndef(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean isActive) {
startOffset= getSequenceNumberForOffset(startOffset);
condOffset= getSequenceNumberForOffset(condOffset);
condEndOffset= getSequenceNumberForOffset(condEndOffset);
- endOffset= getSequenceNumberForOffset(endOffset);
- fDirectives.add(new ASTIfndef(fTranslationUnit, startOffset, condOffset, condEndOffset, endOffset, isActive));
+ // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
+ fDirectives.add(new ASTIfndef(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive));
}
public void encounterPoundIf(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean isActive) {
- startOffset= getSequenceNumberForOffset(startOffset); // there may be a macro expansion
- condOffset= getSequenceNumberForOffset(condOffset); // there may be a macro expansion
+ startOffset= getSequenceNumberForOffset(startOffset);
+ condOffset= getSequenceNumberForOffset(condOffset);
condEndOffset= getSequenceNumberForOffset(condEndOffset);
- endOffset= getSequenceNumberForOffset(endOffset);
- fDirectives.add(new ASTIf(fTranslationUnit, startOffset, condOffset, condEndOffset, endOffset, isActive));
+ // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
+ fDirectives.add(new ASTIf(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive));
}
public void encounterPoundDefine(int startOffset, int nameOffset, int nameEndOffset, int expansionOffset, int endOffset, IMacroBinding macrodef) {
@@ -303,8 +303,8 @@ public class LocationMap implements ILocationResolver {
startOffset= getSequenceNumberForOffset(startOffset);
nameOffset= getSequenceNumberForOffset(nameOffset);
nameEndOffset= getSequenceNumberForOffset(nameEndOffset);
- endOffset= getSequenceNumberForOffset(endOffset);
- fDirectives.add(new ASTUndef(fTranslationUnit, name, startOffset, nameOffset, nameEndOffset, endOffset, definition));
+// endOffset= getSequenceNumberForOffset(endOffset);
+ fDirectives.add(new ASTUndef(fTranslationUnit, name, startOffset, nameOffset, nameEndOffset, definition));
}
public void setRootNode(IASTTranslationUnit root) {
@@ -414,14 +414,15 @@ public class LocationMap implements ILocationResolver {
public IDependencyTree getDependencyTree() {
return new DependencyTree(fRootContext);
}
-
+
+ public void cleanup() {
+ }
+
// stuff to remove from ILocationResolver
public IASTName[] getMacroExpansions() {
throw new UnsupportedOperationException();
}
- public void cleanup() {
- throw new UnsupportedOperationException();
- }
+
// mstodo- locations
public IASTFileLocation flattenLocations(IASTNodeLocation[] locations) {
if (locations.length != 1 || !(locations[0] instanceof IASTFileLocation)) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroDefinitionParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroDefinitionParser.java
index a7c79d25813..c3125f3e7fd 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroDefinitionParser.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroDefinitionParser.java
@@ -25,8 +25,12 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
class MacroDefinitionParser {
static class InvalidMacroDefinitionException extends Exception {
public char[] fName;
- public InvalidMacroDefinitionException(char[] name) {
+ public int fStartOffset;
+ public int fEndOffset;
+ public InvalidMacroDefinitionException(char[] name, int startOffset, int endOffset) {
fName= name;
+ fStartOffset= startOffset;
+ fEndOffset= endOffset;
}
}
@@ -45,14 +49,6 @@ class MacroDefinitionParser {
return fNameToken;
}
- /**
- * In case the expansion was successfully parsed, the start offset is returned.
- * Otherwise the return value is undefined.
- */
- public int getExpansionOffset() {
- return fExpansionOffset;
- }
-
/**
* Parses an entire macro definition. Name must be the next token of the lexer.
*/
@@ -81,7 +77,7 @@ class MacroDefinitionParser {
final char[][] paramList= parseParamList(lexer, name);
final Token replacementToken = lexer.currentToken();
if (replacementToken.getType() != Lexer.tEND_OF_INPUT) {
- throw new InvalidMacroDefinitionException(nameChars);
+ throw new InvalidMacroDefinitionException(nameChars, replacementToken.getOffset(), replacementToken.getEndOffset());
}
if (paramList == null) {
@@ -136,7 +132,7 @@ class MacroDefinitionParser {
if (tt == IToken.tCOMPLETION) {
throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, name);
}
- throw new InvalidMacroDefinitionException(name.getCharImage());
+ throw new InvalidMacroDefinitionException(name.getCharImage(), name.getOffset(), name.getEndOffset());
}
fNameToken= name;
return name;
@@ -178,12 +174,12 @@ class MacroDefinitionParser {
}
// no break;
default:
- throw new InvalidMacroDefinitionException(name.getCharImage());
+ throw new InvalidMacroDefinitionException(name.getCharImage(), name.getOffset(), param.getEndOffset());
}
}
while (fHasVarArgs==0 && next.getType() == IToken.tCOMMA);
if (next.getType() != IToken.tRPAREN) {
- throw new InvalidMacroDefinitionException(name.getCharImage());
+ throw new InvalidMacroDefinitionException(name.getCharImage(), name.getOffset(), next.getEndOffset());
}
next= lex.nextToken(); // consume the closing parenthesis
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java
index 7709539daa5..7aaf72cbc84 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java
@@ -80,23 +80,21 @@ public class MacroExpander {
return t;
}
- public boolean findLParenthesis(IdentityHashMap forbidden) throws OffsetLimitReachedException {
+ public boolean findLParenthesis() throws OffsetLimitReachedException {
Token t= first();
while (t != null) {
switch (t.getType()) {
case CPreprocessor.tSPACE:
+ case CPreprocessor.tNOSPACE:
case Lexer.tNEWLINE:
- break;
case CPreprocessor.tSCOPE_MARKER:
- ((ExpansionBoundary) t).execute(forbidden);
break;
case IToken.tLPAREN:
return true;
default:
return false;
}
- removeFirst();
- t= first();
+ t= (Token) t.getNext();
}
if (fUseCpp) {
@@ -146,7 +144,9 @@ public class MacroExpander {
}
/**
- * Expects that the identifier of the macro expansion has been consumed.
+ * Expects that the identifier of the macro expansion has been consumed. Expands the macro consuming
+ * tokens from the input (to read the parameters) and stores the resulting tokens together
+ * with boundary markers in the result token list.
* Returns the last token of the expansion.
*/
private Token expandOne(Token lastConsumed, PreprocessorMacro macro, IdentityHashMap forbidden, TokenSource input, TokenList result)
@@ -167,7 +167,7 @@ public class MacroExpander {
replaceArgs(macro, clonedArgs, expandedArgs, result);
}
else {
- objStyleTokenPaste(macro, macro.getTokens(fDefinitionParser, fLexOptions), result);
+ objStyleTokenPaste(macro, result);
}
result.append(new ExpansionBoundary(macro, false));
return lastConsumed;
@@ -180,30 +180,29 @@ public class MacroExpander {
switch(t.getType()) {
case CPreprocessor.tSCOPE_MARKER:
((ExpansionBoundary) t).execute(forbidden);
- break;
+ t= input.removeFirst(); // don't change l
+ continue;
case IToken.tIDENTIFIER:
PreprocessorMacro macro= (PreprocessorMacro) fDictionary.get(t.getCharImage());
- if (macro != null && !forbidden.containsKey(macro)) {
- final boolean isFunctionStyle= macro.isFunctionStyle();
- if (!isFunctionStyle || input.findLParenthesis(forbidden)) {
- // mstodo- image location
- fImplicitMacroExpansions.add(fLocationMap.encounterImplicitMacroExpansion(macro, null));
- TokenList replacement= new TokenList();
- if (l != null && l.hasGap(t)) {
- replacement.append(space());
- }
- Token last= expandOne(t, macro, forbidden, input, replacement);
- Token n= input.first();
- if (n != null && last.hasGap(n)) {
- replacement.append(space());
- }
- input.prepend(replacement);
- t= null;
- }
+ // tricky: don't mark function-style macros if you don't find the left parenthesis
+ if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) {
+ result.append(t);
}
- if (t != null) {
+ else if (forbidden.containsKey(macro)) {
t.setType(CPreprocessor.tEXPANDED_IDENTIFIER); // prevent any further expansion
- result.append(t);
+ result.append(t);
+ }
+ else {
+ // mstodo- image location
+ fImplicitMacroExpansions.add(fLocationMap.encounterImplicitMacroExpansion(macro, null));
+
+ TokenList replacement= new TokenList();
+
+ addSpacemarker(l, t, replacement); // start expansion
+ Token last= expandOne(t, macro, forbidden, input, replacement);
+ addSpacemarker(last, input.first(), replacement); // end expansion
+
+ input.prepend(replacement);
}
break;
default:
@@ -215,6 +214,21 @@ public class MacroExpander {
}
}
+ private void addSpacemarker(Token l, Token t, TokenList target) {
+ if (l != null && t != null) {
+ final Object s1= l.fSource;
+ final Object s2= t.fSource;
+ if (s1 == s2 && s1 != null) {
+ if (l.getEndOffset() == t.getOffset()) {
+ target.append(new SimpleToken(CPreprocessor.tNOSPACE, null, 0, 0));
+ }
+ else {
+ target.append(new SimpleToken(CPreprocessor.tSPACE, null, 0, 0));
+ }
+ }
+ }
+ }
+
/**
* Expects that the identifier has been consumed.
* @param forbidden
@@ -225,17 +239,15 @@ public class MacroExpander {
final boolean hasVarargs= macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS;
final int requiredArgs= hasVarargs ? argCount-1 : argCount;
int idx= 0;
- int nesting= 0;
+ int nesting= -1;
for (int i = 0; i < result.length; i++) {
result[i]= new TokenSource(false);
}
- Token lastToken= input.fetchFirst();
- assert lastToken != null && lastToken.getType() == IToken.tLPAREN;
-
boolean complete= false;
boolean isFirstOfArg= true;
- Token space= null;
+ Token lastToken= null;
+ Token spaceMarker= null;
loop: while (true) {
Token t= input.fetchFirst();
if (t == null) {
@@ -244,6 +256,7 @@ public class MacroExpander {
lastToken= t;
switch(t.getType()) {
case Lexer.tEND_OF_INPUT:
+ assert nesting >= 0;
if (fCompletionMode) {
throw new OffsetLimitReachedException(ORIGIN, null);
}
@@ -256,10 +269,14 @@ public class MacroExpander {
continue loop;
case IToken.tLPAREN:
- ++nesting;
+ // the first one sets nesting to zero.
+ if (++nesting == 0) {
+ continue;
+ }
break;
case IToken.tRPAREN:
+ assert nesting >= 0;
if (--nesting < 0) {
complete= true;
break loop;
@@ -267,10 +284,11 @@ public class MacroExpander {
break;
case IToken.tCOMMA:
+ assert nesting >= 0;
if (nesting == 0) {
if (idx < argCount-1) { // next argument
isFirstOfArg= true;
- space= null;
+ spaceMarker= null;
idx++;
continue loop;
}
@@ -290,17 +308,21 @@ public class MacroExpander {
continue loop;
case CPreprocessor.tSPACE:
+ case CPreprocessor.tNOSPACE:
if (!isFirstOfArg) {
- space= t;
+ spaceMarker= t;
}
continue loop;
+
+ default:
+ assert nesting >= 0;
}
if (argCount == 0) {
break loop;
}
- if (space != null) {
- result[idx].append(space);
- space= null;
+ if (spaceMarker != null) {
+ result[idx].append(spaceMarker);
+ spaceMarker= null;
}
result[idx].append(t);
isFirstOfArg= false;
@@ -317,34 +339,37 @@ public class MacroExpander {
}
private void replaceArgs(PreprocessorMacro macro, TokenList[] args, TokenList[] expandedArgs, TokenList result) {
- TokenList input= macro.getTokens(fDefinitionParser, fLexOptions);
+ TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions));
Token l= null;
Token n;
Token pasteArg1= null;
- for (Token t= input.first(); t != null; l=t, t=n) {
+ for (Token t= replacement.first(); t != null; l=t, t=n) {
n= (Token) t.getNext();
boolean pasteNext= n != null && n.getType() == IToken.tPOUNDPOUND;
switch(t.getType()) {
case CPreprocessor.tMACRO_PARAMETER:
- if (l != null && l.hasGap(t)) {
- result.append(space());
- }
int idx= ((PlaceHolderToken) t).getIndex();
if (idx < args.length) { // be defensive
- TokenList arg= pasteNext ? args[idx] : expandedArgs[idx];
- pasteArg1= cloneAndAppend(arg.first(), result, pasteNext);
- }
- if (n != null && t.hasGap(n)) {
- result.append(space());
+ addSpacemarker(l, t, result); // start argument replacement
+ TokenList arg= clone(pasteNext ? args[idx] : expandedArgs[idx]);
+ if (pasteNext) {
+ pasteArg1= arg.last();
+ if (pasteArg1 != null) {
+ result.appendAllButLast(arg);
+ addSpacemarker(result.last(), pasteArg1, result); // start token paste
+ }
+ }
+ else {
+ result.appendAll(arg);
+ addSpacemarker(t, n, result); // end argument replacement
+ }
}
break;
case IToken.tPOUND:
- if (l != null && l.hasGap(t)) {
- result.append(space());
- }
+ addSpacemarker(l, t, result); // start stringify
StringBuffer buf= new StringBuffer();
buf.append('"');
if (n != null && n.getType() == CPreprocessor.tMACRO_PARAMETER) {
@@ -361,76 +386,102 @@ public class MacroExpander {
final char[] image= new char[length];
buf.getChars(0, length, image, 0);
- pasteArg1= appendToResult(new ImageToken(IToken.tSTRING, null, 0, 0, image), result, pasteNext);
- if (!pasteNext && n != null && t.hasGap(n)) {
- result.append(space());
+ Token generated= new ImageToken(IToken.tSTRING, null, 0, 0, image);
+ if (pasteNext) { // start token paste, same as start stringify
+ pasteArg1= generated;
+ }
+ else {
+ result.append(generated);
+ addSpacemarker(t, n, result); // end stringify
}
break;
case IToken.tPOUNDPOUND:
if (pasteArg1 != null) {
Token pasteArg2= null;
- Token rest= null;
+ TokenList rest= null;
if (n != null) {
if (n.getType() == CPreprocessor.tMACRO_PARAMETER) {
idx= ((PlaceHolderToken) n).getIndex();
if (idx < args.length) { // be defensive
- TokenList arg= args[idx];
+ TokenList arg= clone(args[idx]);
pasteArg2= arg.first();
- if (pasteArg2 != null) {
- rest= (Token) pasteArg2.getNext();
- }
// gcc-extension
if (idx == args.length-1 && macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS) {
- if (pasteArg1.getType() == IToken.tCOMMA) {
- if (pasteArg2 == null) {
- pasteArg1= null;
- }
- else {
- pasteArg2.setNext(rest);
- rest= pasteArg2;
- pasteArg2= null;
+ if (pasteArg1.getType() == IToken.tCOMMA) { // no paste operation
+ if (arg.first() != null) {
+ result.append(pasteArg1);
+ rest= arg;
}
+ pasteArg1= pasteArg2= null;
}
}
+ if (pasteArg2 != null) {
+ rest= arg;
+ rest.removeFirst();
+ }
}
}
else {
+ idx= -1;
pasteArg2= n;
}
t= n;
n= (Token) n.getNext();
pasteNext= n != null && n.getType() == IToken.tPOUNDPOUND;
- }
- Token tp= tokenpaste(pasteArg1, pasteArg2, macro);
- if (tp != null) {
- pasteArg1= appendToResult((Token) tp.clone(), result, pasteNext && rest == null);
- }
- if (rest != null) {
- pasteArg1= cloneAndAppend(rest, result, pasteNext);
- }
- if (!pasteNext && n != null && t.hasGap(n)) {
- result.append(space());
+
+ generated= tokenpaste(pasteArg1, pasteArg2, macro);
+ pasteArg1= null;
+
+ if (generated != null) {
+ if (pasteNext && rest == null) {
+ pasteArg1= generated; // no need to mark spaces, done ahead
+ }
+ else {
+ result.append(generated);
+ addSpacemarker(pasteArg2, rest == null ? n : rest.first(), result); // end token paste
+ }
+ }
+ if (rest != null) {
+ if (pasteNext) {
+ pasteArg1= rest.last();
+ if (pasteArg1 != null) {
+ result.appendAllButLast(rest);
+ addSpacemarker(result.last(), pasteArg1, result); // start token paste
+ }
+ }
+ else {
+ result.appendAll(rest);
+ if (idx >= 0) {
+ addSpacemarker(t, n, result); // end argument replacement
+ }
+ }
+ }
}
}
break;
default:
- pasteArg1= appendToResult((Token) t.clone(), result, pasteNext);
+ if (pasteNext) {
+ addSpacemarker(l, t, result); // start token paste
+ pasteArg1= t;
+ }
+ else {
+ result.append(t);
+ }
break;
}
}
}
- private SimpleToken space() {
- return new SimpleToken(CPreprocessor.tSPACE, null, 0, 0);
- }
-
- private void objStyleTokenPaste(PreprocessorMacro macro, TokenList input, TokenList result) {
+ private void objStyleTokenPaste(PreprocessorMacro macro, TokenList result) {
+ TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions));
+
+ Token l= null;
Token n;
Token pasteArg1= null;
- for (Token t= input.first(); t != null; t=n) {
+ for (Token t= replacement.first(); t != null; l=t, t=n) {
n= (Token) t.getNext();
boolean pasteNext= n != null && n.getType() == IToken.tPOUNDPOUND;
@@ -446,47 +497,36 @@ public class MacroExpander {
t= tokenpaste(pasteArg1, pasteArg2, macro);
if (t != null) {
- pasteArg1= appendToResult((Token) t.clone(), result, pasteNext);
+ if (pasteNext) {
+ pasteArg1= t;
+ }
+ else {
+ result.append(t);
+ addSpacemarker(pasteArg2, n, result); // end token paste
+ }
}
}
break;
default:
- pasteArg1= appendToResult((Token) t.clone(), result, pasteNext);
+ if (pasteNext) {
+ addSpacemarker(l, t, result); // start token paste
+ pasteArg1= t;
+ }
+ else {
+ result.append(t);
+ }
break;
}
}
}
- private Token appendToResult(Token t, TokenList result, boolean pasteNext) {
- if (pasteNext) {
- return t;
- }
- result.append(t);
- return null;
- }
-
- private Token cloneAndAppend(Token tokens, TokenList result, boolean pasteNext) {
- Token t= tokens;
- if (t == null) {
- return null;
- }
- Token n= (Token) t.getNext();
- Token p= null;
- while (n != null) {
- result.append((Token) t.clone());
- p= t;
- t= n;
- n= (Token) n.getNext();
- }
- if (t != null && !pasteNext) {
+ private TokenList clone(TokenList tl) {
+ TokenList result= new TokenList();
+ for (Token t= tl.first(); t != null; t= (Token) t.getNext()) {
result.append((Token) t.clone());
- return null;
}
- if (p != null && p.hasGap(t)) {
- result.append(space());
- }
- return t;
+ return result;
}
private Token tokenpaste(Token arg1, Token arg2, PreprocessorMacro macro) {
@@ -522,9 +562,10 @@ public class MacroExpander {
Token l= null;
Token n;
boolean space= false;
- for (; t != null; l=t, t= n) {
+ for (; t != null; l=t, t=n) {
n= (Token) t.getNext();
- if (!space && l != null && l.hasGap(t)) {
+ if (!space && l != null && l.fSource != null && l.fSource == t.fSource &&
+ l.getEndOffset() != t.getOffset()) {
buf.append(' ');
space= true;
}
@@ -551,6 +592,9 @@ public class MacroExpander {
}
break;
+ case CPreprocessor.tNOSPACE:
+ break;
+
default:
buf.append(t.getCharImage());
space= false;
@@ -581,6 +625,7 @@ public class MacroExpander {
break;
case CPreprocessor.tSCOPE_MARKER:
case CPreprocessor.tSPACE:
+ case CPreprocessor.tNOSPACE:
replacement.removeBehind(l);
continue;
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java
index 19fd43da082..6eb93ed7fa2 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java
@@ -127,6 +127,14 @@ class ObjectStyleMacro extends PreprocessorMacro {
}
}
+ public int getExpansionOffset() {
+ return fExpansionOffset;
+ }
+
+ public int getExpansionEndOffset() {
+ return fEndOffset;
+ }
+
private void setSource(Token t) {
while (t != null) {
t.fSource= this;
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenList.java
index d78e77b5e74..3ba2d02bffb 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenList.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenList.java
@@ -26,7 +26,7 @@ class TokenList {
}
}
- final public void append(Token t) {
+ public final void append(Token t) {
if (fFirst == null) {
fFirst= fLast= t;
}
@@ -37,7 +37,30 @@ class TokenList {
t.setNext(null);
}
- final public void prepend(TokenList prepend) {
+ public final void appendAll(TokenList tl) {
+ final Token t= tl.first();
+ if (t != null) {
+ if (fFirst == null) {
+ fFirst= tl.fFirst;
+ }
+ else {
+ fLast.setNext(tl.fFirst);
+ }
+ fLast= tl.fLast;
+ }
+ tl.fFirst= tl.fLast= null;
+ }
+
+ public final void appendAllButLast(TokenList tl) {
+ Token t= tl.first();
+ if (t != null) {
+ for (Token n= (Token) t.getNext(); n != null; t=n, n= (Token) n.getNext()) {
+ append(t);
+ }
+ }
+ }
+
+ public final void prepend(TokenList prepend) {
final Token first= prepend.fFirst;
if (first != null) {
final Token last= prepend.fLast;
@@ -49,7 +72,7 @@ class TokenList {
}
}
- final public TokenList cloneTokens() {
+ public final TokenList cloneTokens() {
TokenList result= new TokenList();
for (Token t= fFirst; t != null; t= (Token) t.getNext()) {
if (t.getType() != CPreprocessor.tSCOPE_MARKER) {
@@ -59,10 +82,14 @@ class TokenList {
return result;
}
- final public Token first() {
+ public final Token first() {
return fFirst;
}
+ public final Token last() {
+ return fLast;
+ }
+
final void removeBehind(Token l) {
if (l == null) {
Token t= fFirst;
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java
index 728df09851d..cf6f54564e1 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java
@@ -124,6 +124,7 @@ public class TokenUtil {
case IGCCToken.tMAX: return Keywords.cpMAX;
case CPreprocessor.tSPACE: return SPACE;
+ case CPreprocessor.tNOSPACE: return CharArrayUtils.EMPTY;
default:
return CharArrayUtils.EMPTY;

Back to the top