mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Dynamic macros and whitespace in macro-explorer, bug 23540.
This commit is contained in:
parent
13bad2303e
commit
2bf1905d6c
14 changed files with 300 additions and 158 deletions
|
@ -45,6 +45,8 @@ public class ExpansionExplorerTests extends BaseTestCase {
|
|||
}
|
||||
final MacroExpander expander= createExpander(input[0]);
|
||||
final String original= input[1];
|
||||
|
||||
verifyStepCount(expander, original, steps);
|
||||
|
||||
verifyStep(expander, original, Integer.MAX_VALUE, original, input[steps+1]);
|
||||
for (i= 0; i < steps; i++) {
|
||||
|
@ -52,18 +54,24 @@ public class ExpansionExplorerTests extends BaseTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private void verifyStepCount(MacroExpander expander, String original, int steps) {
|
||||
MacroExpansionTracker tracker= new MacroExpansionTracker(Integer.MAX_VALUE);
|
||||
expander.expand(original, tracker, "", 1);
|
||||
assertEquals(steps, tracker.getStepCount());
|
||||
}
|
||||
|
||||
private void verifyStep(MacroExpander expander, String original, int step, String expectedPre,
|
||||
String expectedPost) {
|
||||
MacroExpansionTracker tracker= new MacroExpansionTracker(step);
|
||||
expander.expand(original, tracker);
|
||||
expander.expand(original, tracker, "", 1);
|
||||
String pre = tracker.getCodeBeforeStep();
|
||||
ReplaceEdit replacement = tracker.getReplacement();
|
||||
assertNotNull(pre);
|
||||
assertNotNull(replacement);
|
||||
String post= apply(pre, replacement);
|
||||
|
||||
assertEquals(expectedPre, pre);
|
||||
assertEquals(expectedPost, post);
|
||||
assertEquals("incorrect value pre " + step, expectedPre, pre);
|
||||
assertEquals("incorrect value post " + step, expectedPost, post);
|
||||
}
|
||||
|
||||
private String apply(String pre, ReplaceEdit replacement) {
|
||||
|
@ -91,7 +99,7 @@ public class ExpansionExplorerTests extends BaseTestCase {
|
|||
|
||||
// B
|
||||
public void testNoOp() throws Exception {
|
||||
performTest(1);
|
||||
performTest(0);
|
||||
}
|
||||
|
||||
// #define A B
|
||||
|
@ -208,6 +216,69 @@ public class ExpansionExplorerTests extends BaseTestCase {
|
|||
performTest(7);
|
||||
}
|
||||
|
||||
// #define id(x) x
|
||||
|
||||
// id(
|
||||
// id(a))
|
||||
|
||||
// id(
|
||||
// a)
|
||||
|
||||
// a
|
||||
public void testNewline() throws Exception {
|
||||
performTest(2);
|
||||
}
|
||||
|
||||
// #define f x _a _b x
|
||||
// #define _a a
|
||||
// #define _b b
|
||||
|
||||
// f
|
||||
|
||||
// x _a _b x
|
||||
|
||||
// x a _b x
|
||||
|
||||
// x a b x
|
||||
public void testSpace() throws Exception {
|
||||
performTest(3);
|
||||
}
|
||||
|
||||
// #define L __LINE__
|
||||
// #define x(a) a
|
||||
|
||||
// x(L)
|
||||
|
||||
// x(__LINE__)
|
||||
|
||||
// x(1)
|
||||
|
||||
// 1
|
||||
public void testLineNumber() throws Exception {
|
||||
performTest(3);
|
||||
}
|
||||
|
||||
// #define L __LINE__
|
||||
// #define x(a,b) a,b
|
||||
|
||||
// x(L,
|
||||
// L)
|
||||
|
||||
// x(__LINE__,
|
||||
// L)
|
||||
|
||||
// x(2,
|
||||
// L)
|
||||
|
||||
// x(2,
|
||||
// __LINE__)
|
||||
|
||||
// x(2,
|
||||
// 2)
|
||||
|
||||
// 2,2
|
||||
public void testLineNumber2() throws Exception {
|
||||
performTest(5);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -639,6 +639,19 @@ public class PreprocessorTests extends PreprocessorTestsBase {
|
|||
validateProblemCount(0);
|
||||
}
|
||||
|
||||
|
||||
// #define A(x,y,z) x + y + z
|
||||
// #define _t t
|
||||
// A ( _t , , _t )
|
||||
public void testEmptyToken() throws Exception {
|
||||
initializeScanner();
|
||||
validateIdentifier("t");
|
||||
validateToken(IToken.tPLUS);
|
||||
validateToken(IToken.tPLUS);
|
||||
validateIdentifier("t");
|
||||
}
|
||||
|
||||
|
||||
// #define FOO 5
|
||||
// # define BAR 10
|
||||
// int x = FOO + BAR;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004, 2007 IBM Corporation and others.
|
||||
* Copyright (c) 2004, 2008 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
|
||||
|
@ -41,9 +41,7 @@ public interface IASTPreprocessorMacroDefinition extends
|
|||
public void setName(IASTName name);
|
||||
|
||||
/**
|
||||
* Get the macro expansion.
|
||||
*
|
||||
* @return String
|
||||
* Returns the macro expansion, or an empty string for dynamic style macros.
|
||||
*/
|
||||
public String getExpansion();
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004, 2005 IBM Corporation and others.
|
||||
* Copyright (c) 2004, 2008 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM - Initial API and implementation
|
||||
* IBM - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.dom.ast;
|
||||
|
||||
|
@ -29,7 +30,7 @@ public interface IMacroBinding extends IBinding {
|
|||
char[][] getParameterList();
|
||||
|
||||
/**
|
||||
* Returns the expansion of this macro definition.
|
||||
* Returns the expansion of this macro definition, or <code>null</code> for dynamic-style macros.
|
||||
* @since 5.0
|
||||
*/
|
||||
char[] getExpansion();
|
||||
|
@ -44,7 +45,7 @@ public interface IMacroBinding extends IBinding {
|
|||
char[][] getParameterPlaceholderList();
|
||||
|
||||
/**
|
||||
* Returns the image of the expansion (also containing comments).
|
||||
* Returns the image of the expansion (also containing comments), or <code>null</code> for dynamic style macros.
|
||||
* @since 5.0
|
||||
*/
|
||||
char[] getExpansionImage();
|
||||
|
|
|
@ -230,7 +230,7 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
|
|||
}
|
||||
}
|
||||
|
||||
class ASTObjectStyleMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessorObjectStyleMacroDefinition {
|
||||
class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessorObjectStyleMacroDefinition {
|
||||
private final ASTPreprocessorName fName;
|
||||
private final int fExpansionNumber;
|
||||
private final int fExpansionOffset;
|
||||
|
@ -238,7 +238,7 @@ class ASTObjectStyleMacroDefinition extends ASTPreprocessorNode implements IASTP
|
|||
/**
|
||||
* Regular constructor.
|
||||
*/
|
||||
public ASTObjectStyleMacroDefinition(IASTTranslationUnit parent, IMacroBinding macro,
|
||||
public ASTMacroDefinition(IASTTranslationUnit parent, IMacroBinding macro,
|
||||
int startNumber, int nameNumber, int nameEndNumber, int expansionNumber, int endNumber) {
|
||||
super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber);
|
||||
fExpansionNumber= expansionNumber;
|
||||
|
@ -250,7 +250,7 @@ class ASTObjectStyleMacroDefinition extends ASTPreprocessorNode implements IASTP
|
|||
* Constructor for built-in macros
|
||||
* @param expansionOffset
|
||||
*/
|
||||
public ASTObjectStyleMacroDefinition(IASTTranslationUnit parent, IMacroBinding macro, IASTFileLocation floc, int expansionOffset) {
|
||||
public ASTMacroDefinition(IASTTranslationUnit parent, IMacroBinding macro, IASTFileLocation floc, int expansionOffset) {
|
||||
super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, -1, -1);
|
||||
fName= new ASTBuiltinName(this, IASTPreprocessorMacroDefinition.MACRO_NAME, floc, macro.getNameCharArray(), macro);
|
||||
fExpansionNumber= -1;
|
||||
|
@ -270,7 +270,12 @@ class ASTObjectStyleMacroDefinition extends ASTPreprocessorNode implements IASTP
|
|||
}
|
||||
|
||||
public String getExpansion() {
|
||||
return new String(getMacro().getExpansion());
|
||||
final char[] expansion = getMacro().getExpansion();
|
||||
// for dynamic style macros return an empty string
|
||||
if (expansion == null) {
|
||||
return ""; //$NON-NLS-1$
|
||||
}
|
||||
return new String(expansion);
|
||||
}
|
||||
|
||||
public IASTName getName() {
|
||||
|
@ -306,7 +311,10 @@ class ASTObjectStyleMacroDefinition extends ASTPreprocessorNode implements IASTP
|
|||
if (fExpansionOffset >= 0) {
|
||||
String fileName= fName.getContainingFilename();
|
||||
if (fileName != null) {
|
||||
return new ASTFileLocationForBuiltins(fileName, fExpansionOffset, getMacro().getExpansionImage().length);
|
||||
final char[] expansionImage = getMacro().getExpansionImage();
|
||||
if (expansionImage != null) {
|
||||
return new ASTFileLocationForBuiltins(fileName, fExpansionOffset, expansionImage.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -328,7 +336,7 @@ class ASTMacroParameter extends ASTPreprocessorNode implements IASTFunctionStyle
|
|||
public void setParameter(String value) {assert false;}
|
||||
}
|
||||
|
||||
class ASTFunctionStyleMacroDefinition extends ASTObjectStyleMacroDefinition implements IASTPreprocessorFunctionStyleMacroDefinition {
|
||||
class ASTFunctionStyleMacroDefinition extends ASTMacroDefinition implements IASTPreprocessorFunctionStyleMacroDefinition {
|
||||
/**
|
||||
* Regular constructor.
|
||||
*/
|
||||
|
|
|
@ -14,8 +14,6 @@ package org.eclipse.cdt.internal.core.parser.scanner;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -66,8 +64,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
public static final int tNOSPACE= IToken.FIRST_RESERVED_PREPROCESSOR+4;
|
||||
public static final int tMACRO_PARAMETER= IToken.FIRST_RESERVED_PREPROCESSOR+5;
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
@ -83,6 +79,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
private static final ObjectStyleMacro __STDC_HOSTED__ = new ObjectStyleMacro("__STDC_HOSTED_".toCharArray(), ONE); //$NON-NLS-1$
|
||||
private static final ObjectStyleMacro __STDC_VERSION__ = new ObjectStyleMacro("__STDC_VERSION_".toCharArray(), "199901L".toCharArray()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
private static final DynamicStyleMacro __FILE__= new FileMacro("__FILE__".toCharArray()); //$NON-NLS-1$
|
||||
private static final DynamicStyleMacro __DATE__= new DateMacro("__DATE__".toCharArray()); //$NON-NLS-1$
|
||||
private static final DynamicStyleMacro __TIME__ = new TimeMacro("__TIME__".toCharArray()); //$NON-NLS-1$
|
||||
private static final DynamicStyleMacro __LINE__ = new LineMacro("__LINE__".toCharArray()); //$NON-NLS-1$
|
||||
|
||||
private interface IIncludeFileTester {
|
||||
Object checkFile(String path, String fileName);
|
||||
|
@ -104,63 +104,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
};
|
||||
|
||||
// standard built-ins
|
||||
final private DynamicStyleMacro __FILE__= new DynamicStyleMacro("__FILE__".toCharArray()) { //$NON-NLS-1$
|
||||
public Token execute() {
|
||||
StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$
|
||||
buffer.append(getCurrentFilename());
|
||||
buffer.append('\"');
|
||||
return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
|
||||
}
|
||||
};
|
||||
final private DynamicStyleMacro __DATE__= new DynamicStyleMacro("__DATE__".toCharArray()) { //$NON-NLS-1$
|
||||
final private void append(StringBuffer buffer, int value) {
|
||||
if (value < 10)
|
||||
buffer.append("0"); //$NON-NLS-1$
|
||||
buffer.append(value);
|
||||
}
|
||||
|
||||
public Token execute() {
|
||||
StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$
|
||||
Calendar cal = Calendar.getInstance();
|
||||
DateFormatSymbols dfs= new DateFormatSymbols();
|
||||
buffer.append(dfs.getShortMonths()[cal.get(Calendar.MONTH)]);
|
||||
buffer.append(" "); //$NON-NLS-1$
|
||||
append(buffer, cal.get(Calendar.DAY_OF_MONTH));
|
||||
buffer.append(" "); //$NON-NLS-1$
|
||||
buffer.append(cal.get(Calendar.YEAR));
|
||||
buffer.append("\""); //$NON-NLS-1$
|
||||
return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
|
||||
}
|
||||
};
|
||||
|
||||
final private DynamicStyleMacro __TIME__ = new DynamicStyleMacro("__TIME__".toCharArray()) { //$NON-NLS-1$
|
||||
final private void append(StringBuffer buffer, int value) {
|
||||
if (value < 10)
|
||||
buffer.append("0"); //$NON-NLS-1$
|
||||
buffer.append(value);
|
||||
}
|
||||
|
||||
public Token execute() {
|
||||
StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$
|
||||
Calendar cal = Calendar.getInstance();
|
||||
append(buffer, cal.get(Calendar.HOUR_OF_DAY));
|
||||
buffer.append(":"); //$NON-NLS-1$
|
||||
append(buffer, cal.get(Calendar.MINUTE));
|
||||
buffer.append(":"); //$NON-NLS-1$
|
||||
append(buffer, cal.get(Calendar.SECOND));
|
||||
buffer.append("\""); //$NON-NLS-1$
|
||||
return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
|
||||
}
|
||||
};
|
||||
|
||||
final private DynamicStyleMacro __LINE__ = new DynamicStyleMacro("__LINE__".toCharArray()) { //$NON-NLS-1$
|
||||
public Token execute() {
|
||||
int lineNumber= fLocationMap.getCurrentLineNumber(fCurrentContext.currentLexerToken().getOffset());
|
||||
return new TokenWithImage(IToken.tINTEGER, null, 0, 0, Long.toString(lineNumber).toCharArray());
|
||||
}
|
||||
};
|
||||
|
||||
final private IParserLogService fLog;
|
||||
final private IIndexBasedCodeReaderFactory fCodeReaderFactory;
|
||||
private final ExpressionEvaluator fExpressionEvaluator;
|
||||
|
|
|
@ -48,7 +48,7 @@ public class LocationMap implements ILocationResolver {
|
|||
private ArrayList<ASTPreprocessorNode> fDirectives= new ArrayList<ASTPreprocessorNode>();
|
||||
private ArrayList<ASTProblem> fProblems= new ArrayList<ASTProblem>();
|
||||
private ArrayList<ASTComment> fComments= new ArrayList<ASTComment>();
|
||||
private ArrayList<ASTObjectStyleMacroDefinition> fBuiltinMacros= new ArrayList<ASTObjectStyleMacroDefinition>();
|
||||
private ArrayList<ASTMacroDefinition> fBuiltinMacros= new ArrayList<ASTMacroDefinition>();
|
||||
private ArrayList<IASTName> fMacroReferences= new ArrayList<IASTName>();
|
||||
|
||||
private LocationCtxFile fRootContext= null;
|
||||
|
@ -69,12 +69,12 @@ public class LocationMap implements ILocationResolver {
|
|||
}
|
||||
|
||||
private void registerPredefinedMacro(IMacroBinding macro, IASTFileLocation nameloc, int expansionOffset) {
|
||||
ASTObjectStyleMacroDefinition astmacro;
|
||||
ASTMacroDefinition astmacro;
|
||||
if (macro.isFunctionStyle()) {
|
||||
astmacro= new ASTFunctionStyleMacroDefinition(fTranslationUnit, macro, nameloc, expansionOffset);
|
||||
}
|
||||
else {
|
||||
astmacro= new ASTObjectStyleMacroDefinition(fTranslationUnit, macro, nameloc, expansionOffset);
|
||||
astmacro= new ASTMacroDefinition(fTranslationUnit, macro, nameloc, expansionOffset);
|
||||
}
|
||||
fBuiltinMacros.add(astmacro);
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ public class LocationMap implements ILocationResolver {
|
|||
endOffset= getSequenceNumberForOffset(endOffset);
|
||||
ASTPreprocessorNode astMacro;
|
||||
if (!macrodef.isFunctionStyle()) {
|
||||
astMacro= new ASTObjectStyleMacroDefinition(fTranslationUnit, macrodef, startOffset, nameOffset, nameEndOffset, expansionOffset, endOffset);
|
||||
astMacro= new ASTMacroDefinition(fTranslationUnit, macrodef, startOffset, nameOffset, nameEndOffset, expansionOffset, endOffset);
|
||||
}
|
||||
else {
|
||||
astMacro= new ASTFunctionStyleMacroDefinition(fTranslationUnit, macrodef, startOffset, nameOffset, nameEndOffset, expansionOffset, endOffset);
|
||||
|
|
|
@ -136,6 +136,11 @@ public class MacroExpander {
|
|||
private int fStartOffset;
|
||||
private int fEndOffset;
|
||||
|
||||
// for using the expander to track expansions
|
||||
private String fFixedCurrentFilename;
|
||||
private int fFixedLineNumber;
|
||||
private char[] fFixedInput;
|
||||
|
||||
public MacroExpander(ILexerLog log, CharArrayMap<PreprocessorMacro> macroDictionary, LocationMap locationMap, LexerOptions lexOptions) {
|
||||
fDictionary= macroDictionary;
|
||||
fLocationMap= locationMap;
|
||||
|
@ -173,10 +178,13 @@ public class MacroExpander {
|
|||
* Method for tracking macro expansions.
|
||||
* @since 5.0
|
||||
*/
|
||||
public void expand(String beforeExpansion, MacroExpansionTracker tracker) {
|
||||
Lexer lexer= new Lexer(beforeExpansion.toCharArray(), fLexOptions, fLog, this);
|
||||
public void expand(String beforeExpansion, MacroExpansionTracker tracker, String filePath, int lineNumber) {
|
||||
fImplicitMacroExpansions.clear();
|
||||
fImageLocationInfos.clear();
|
||||
fFixedInput= beforeExpansion.toCharArray();
|
||||
fFixedCurrentFilename= filePath;
|
||||
fFixedLineNumber= lineNumber;
|
||||
Lexer lexer= new Lexer(fFixedInput, fLexOptions, fLog, this);
|
||||
|
||||
try {
|
||||
tracker.start(lexer);
|
||||
|
@ -362,17 +370,28 @@ public class MacroExpander {
|
|||
return null;
|
||||
}
|
||||
|
||||
private void addSpacemarker(Token l, Token t, TokenList target) {
|
||||
private static boolean isNeighborInSource(Token l, Token t) {
|
||||
if (l != null && t != null) {
|
||||
final Object s1= l.fSource;
|
||||
final Object s2= t.fSource;
|
||||
if (s1 == s2 && s1 != null && l.getType() != CPreprocessor.tSPACE) {
|
||||
if (l.getEndOffset() == t.getOffset()) {
|
||||
target.append(new Token(CPreprocessor.tNOSPACE, null, 0, 0));
|
||||
}
|
||||
else {
|
||||
target.append(new Token(CPreprocessor.tSPACE, s1, l.getEndOffset(), t.getOffset()));
|
||||
}
|
||||
return s1 == s2 && s1 != null &&
|
||||
l.getType() != CPreprocessor.tSPACE && t.getType() != CPreprocessor.tSPACE;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
static boolean hasImplicitSpace(Token l, Token t) {
|
||||
return isNeighborInSource(l, t) && l.getEndOffset() != t.getOffset();
|
||||
}
|
||||
|
||||
static void addSpacemarker(Token l, Token t, TokenList target) {
|
||||
if (isNeighborInSource(l, t)) {
|
||||
if (l.getEndOffset() == t.getOffset()) {
|
||||
target.append(new Token(CPreprocessor.tNOSPACE, null, 0, 0));
|
||||
}
|
||||
else {
|
||||
target.append(new Token(CPreprocessor.tSPACE, l.fSource, l.getEndOffset(), t.getOffset()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -397,7 +416,7 @@ public class MacroExpander {
|
|||
boolean complete= false;
|
||||
boolean isFirstOfArg= true;
|
||||
Token lastToken= null;
|
||||
Token spaceMarker= null;
|
||||
TokenList spaceMarkers= new TokenList();
|
||||
loop: while (true) {
|
||||
Token t= input.fetchFirst();
|
||||
if (t == null) {
|
||||
|
@ -408,6 +427,7 @@ public class MacroExpander {
|
|||
case IToken.tEND_OF_INPUT:
|
||||
case IToken.tCOMPLETION:
|
||||
case CPreprocessor.tSCOPE_MARKER:
|
||||
case Lexer.tNEWLINE:
|
||||
break;
|
||||
default:
|
||||
tracker.addFunctionStyleMacroExpansionToken((Token) t.clone());
|
||||
|
@ -449,7 +469,7 @@ public class MacroExpander {
|
|||
if (nesting == 0) {
|
||||
if (idx < argCount-1) { // next argument
|
||||
isFirstOfArg= true;
|
||||
spaceMarker= null;
|
||||
spaceMarkers.clear();
|
||||
idx++;
|
||||
continue loop;
|
||||
}
|
||||
|
@ -471,7 +491,7 @@ public class MacroExpander {
|
|||
case CPreprocessor.tSPACE:
|
||||
case CPreprocessor.tNOSPACE:
|
||||
if (!isFirstOfArg) {
|
||||
spaceMarker= t;
|
||||
spaceMarkers.append(t);
|
||||
}
|
||||
continue loop;
|
||||
|
||||
|
@ -481,10 +501,7 @@ public class MacroExpander {
|
|||
if (argCount == 0) {
|
||||
break loop;
|
||||
}
|
||||
if (spaceMarker != null) {
|
||||
result[idx].append(spaceMarker);
|
||||
spaceMarker= null;
|
||||
}
|
||||
result[idx].appendAll(spaceMarkers);
|
||||
result[idx].append(t);
|
||||
isFirstOfArg= false;
|
||||
}
|
||||
|
@ -500,7 +517,7 @@ public class MacroExpander {
|
|||
}
|
||||
|
||||
private void replaceArgs(PreprocessorMacro macro, TokenList[] args, TokenList[] expandedArgs, TokenList result) {
|
||||
TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions));
|
||||
TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions, this));
|
||||
|
||||
Token l= null;
|
||||
Token n;
|
||||
|
@ -638,7 +655,7 @@ public class MacroExpander {
|
|||
|
||||
private BitSet getParamUsage(PreprocessorMacro macro) {
|
||||
final BitSet result= new BitSet();
|
||||
final TokenList replacement= macro.getTokens(fDefinitionParser, fLexOptions);
|
||||
final TokenList replacement= macro.getTokens(fDefinitionParser, fLexOptions, this);
|
||||
|
||||
Token l= null;
|
||||
Token n;
|
||||
|
@ -684,7 +701,7 @@ public class MacroExpander {
|
|||
}
|
||||
|
||||
private void objStyleTokenPaste(PreprocessorMacro macro, TokenList result) {
|
||||
TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions));
|
||||
TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions, this));
|
||||
|
||||
Token l= null;
|
||||
Token n;
|
||||
|
@ -862,9 +879,33 @@ public class MacroExpander {
|
|||
}
|
||||
}
|
||||
|
||||
static boolean hasImplicitSpace(Token l, Token t) {
|
||||
return l != null &&
|
||||
l.fSource != null && l.fSource == t.fSource &&
|
||||
l.getEndOffset() != t.getOffset() && t.getType() != CPreprocessor.tSPACE;
|
||||
int getCurrentLineNumber() {
|
||||
if (fFixedInput != null) {
|
||||
return fFixedLineNumber + countNewlines(fFixedInput);
|
||||
}
|
||||
if (fLocationMap != null) {
|
||||
return fLocationMap.getCurrentLineNumber(fEndOffset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int countNewlines(char[] input) {
|
||||
int nl= 0;
|
||||
for (int i = 0; i < input.length && i<fEndOffset; i++) {
|
||||
if (input[i] == '\n') {
|
||||
nl++;
|
||||
}
|
||||
}
|
||||
return nl;
|
||||
}
|
||||
|
||||
String getCurrentFilename() {
|
||||
if (fFixedCurrentFilename != null) {
|
||||
return fFixedCurrentFilename;
|
||||
}
|
||||
if (fLocationMap != null) {
|
||||
return fLocationMap.getCurrentFilePath();
|
||||
}
|
||||
return ""; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
||||
* Copyright (c) 2008 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
|
||||
|
@ -252,7 +252,9 @@ public class MacroExpansionTracker {
|
|||
TokenList p = minfo.fArguments.get(pcount);
|
||||
if (p != null) {
|
||||
active = false;
|
||||
addSpacemarker(t, n, result);
|
||||
if (n != null && n.getType() != IToken.tCOMMA && n.getType() != IToken.tRPAREN) {
|
||||
MacroExpander.addSpacemarker(t, n, result);
|
||||
}
|
||||
result.appendAll(p);
|
||||
}
|
||||
}
|
||||
|
@ -261,7 +263,7 @@ public class MacroExpansionTracker {
|
|||
|
||||
case IToken.tRPAREN:
|
||||
if (!active && nesting == 0) {
|
||||
addSpacemarker(l, t, result);
|
||||
MacroExpander.addSpacemarker(l, t, result);
|
||||
active= true;
|
||||
}
|
||||
if (active) {
|
||||
|
@ -276,13 +278,15 @@ public class MacroExpansionTracker {
|
|||
if (nesting == 0) {
|
||||
if (++pcount < minfo.fArguments.size()) {
|
||||
if (!active) {
|
||||
addSpacemarker(l, t, result);
|
||||
MacroExpander.addSpacemarker(l, t, result);
|
||||
}
|
||||
result.append(t);
|
||||
TokenList p = minfo.fArguments.get(pcount);
|
||||
active = p == null;
|
||||
if (!active) {
|
||||
addSpacemarker(t, n, result);
|
||||
if (n != null && n.getType() != IToken.tCOMMA && n.getType() != IToken.tRPAREN) {
|
||||
MacroExpander.addSpacemarker(t, n, result);
|
||||
}
|
||||
result.appendAll(p);
|
||||
}
|
||||
}
|
||||
|
@ -299,22 +303,6 @@ public class MacroExpansionTracker {
|
|||
}
|
||||
}
|
||||
|
||||
private void addSpacemarker(Token l, Token t, TokenList target) {
|
||||
Token tl= target.last();
|
||||
if (tl != null && tl.getType() == CPreprocessor.tSPACE) {
|
||||
return;
|
||||
}
|
||||
if (l != null && t != null) {
|
||||
final Object s1= l.fSource;
|
||||
final Object s2= t.fSource;
|
||||
if (s1 == s2 && s1 != null && l.getType() != CPreprocessor.tSPACE) {
|
||||
if (l.getEndOffset() != t.getOffset()) {
|
||||
target.append(new Token(CPreprocessor.tSPACE, s1, l.getEndOffset(), t.getOffset()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the tracker that the function style macro has been expanded.
|
||||
*/
|
||||
|
|
|
@ -49,6 +49,7 @@ public class MultiMacroExpansionExplorer extends MacroExpansionExplorer {
|
|||
private final char[] fSource;
|
||||
private final int[] fBoundaries;
|
||||
private final SingleMacroExpansionExplorer[] fDelegates;
|
||||
private String fFilePath;
|
||||
|
||||
public MultiMacroExpansionExplorer(IASTTranslationUnit tu, IASTFileLocation loc) {
|
||||
if (tu == null || loc == null || loc.getNodeLength() == 0) {
|
||||
|
@ -75,6 +76,7 @@ public class MultiMacroExpansionExplorer extends MacroExpansionExplorer {
|
|||
}
|
||||
}
|
||||
|
||||
fFilePath= tu.getFilePath();
|
||||
fSource= resolver.getUnpreprocessedSignature(loc);
|
||||
fBoundaries= new int[count*2+1];
|
||||
fDelegates= new SingleMacroExpansionExplorer[count];
|
||||
|
@ -91,7 +93,7 @@ public class MultiMacroExpansionExplorer extends MacroExpansionExplorer {
|
|||
fBoundaries[++bidx]= from;
|
||||
fBoundaries[++bidx]= to;
|
||||
fDelegates[++didx]= new SingleMacroExpansionExplorer(new String(fSource, from, to-from), ref,
|
||||
resolver.getImplicitMacroReferences(ref));
|
||||
resolver.getImplicitMacroReferences(ref), fFilePath, refLoc.getStartingLineNumber());
|
||||
}
|
||||
}
|
||||
fBoundaries[++bidx]= fSource.length;
|
||||
|
|
|
@ -10,9 +10,13 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.parser.scanner;
|
||||
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.util.Calendar;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ILinkage;
|
||||
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.parser.IToken;
|
||||
import org.eclipse.cdt.core.parser.Keywords;
|
||||
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
|
||||
import org.eclipse.cdt.internal.core.dom.Linkage;
|
||||
|
@ -83,27 +87,7 @@ abstract class PreprocessorMacro implements IMacroBinding {
|
|||
buf.append(')');
|
||||
return buf.toString();
|
||||
}
|
||||
public abstract TokenList getTokens(MacroDefinitionParser parser, LexerOptions lexOptions);
|
||||
}
|
||||
|
||||
abstract class DynamicStyleMacro extends PreprocessorMacro {
|
||||
|
||||
public DynamicStyleMacro(char[] name) {
|
||||
super(name);
|
||||
}
|
||||
public char[] getExpansion() {
|
||||
return getExpansionImage();
|
||||
}
|
||||
public char[] getExpansionImage() {
|
||||
return execute().getCharImage();
|
||||
}
|
||||
public abstract Token execute();
|
||||
|
||||
public TokenList getTokens(MacroDefinitionParser mdp, LexerOptions lexOptions) {
|
||||
TokenList result= new TokenList();
|
||||
result.append(execute());
|
||||
return result;
|
||||
}
|
||||
public abstract TokenList getTokens(MacroDefinitionParser parser, LexerOptions lexOptions, MacroExpander expander);
|
||||
}
|
||||
|
||||
class ObjectStyleMacro extends PreprocessorMacro {
|
||||
|
@ -158,7 +142,7 @@ class ObjectStyleMacro extends PreprocessorMacro {
|
|||
return result;
|
||||
}
|
||||
|
||||
public TokenList getTokens(MacroDefinitionParser mdp, LexerOptions lexOptions) {
|
||||
public TokenList getTokens(MacroDefinitionParser mdp, LexerOptions lexOptions, MacroExpander expander) {
|
||||
if (fExpansionTokens == null) {
|
||||
fExpansionTokens= new TokenList();
|
||||
Lexer lex= new Lexer(fExpansion, fExpansionOffset, fEndOffset, lexOptions, ILexerLog.NULL, this);
|
||||
|
@ -267,3 +251,90 @@ class FunctionStyleMacro extends ObjectStyleMacro {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DynamicStyleMacro extends PreprocessorMacro {
|
||||
|
||||
public DynamicStyleMacro(char[] name) {
|
||||
super(name);
|
||||
}
|
||||
public char[] getExpansion() {
|
||||
return null;
|
||||
}
|
||||
public char[] getExpansionImage() {
|
||||
return null;
|
||||
}
|
||||
public abstract Token execute(MacroExpander expander);
|
||||
|
||||
public TokenList getTokens(MacroDefinitionParser mdp, LexerOptions lexOptions, MacroExpander expander) {
|
||||
TokenList result= new TokenList();
|
||||
result.append(execute(expander));
|
||||
return result;
|
||||
}
|
||||
|
||||
final protected void append(StringBuffer buffer, int value) {
|
||||
if (value < 10)
|
||||
buffer.append("0"); //$NON-NLS-1$
|
||||
buffer.append(value);
|
||||
}
|
||||
}
|
||||
|
||||
final class DateMacro extends DynamicStyleMacro {
|
||||
DateMacro(char[] name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public Token execute(MacroExpander expander) {
|
||||
StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$
|
||||
Calendar cal = Calendar.getInstance();
|
||||
DateFormatSymbols dfs= new DateFormatSymbols();
|
||||
buffer.append(dfs.getShortMonths()[cal.get(Calendar.MONTH)]);
|
||||
buffer.append(" "); //$NON-NLS-1$
|
||||
append(buffer, cal.get(Calendar.DAY_OF_MONTH));
|
||||
buffer.append(" "); //$NON-NLS-1$
|
||||
buffer.append(cal.get(Calendar.YEAR));
|
||||
buffer.append("\""); //$NON-NLS-1$
|
||||
return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
|
||||
}
|
||||
}
|
||||
|
||||
final class FileMacro extends DynamicStyleMacro {
|
||||
FileMacro(char[] name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public Token execute(MacroExpander expander) {
|
||||
StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$
|
||||
buffer.append(expander.getCurrentFilename());
|
||||
buffer.append('\"');
|
||||
return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
|
||||
}
|
||||
}
|
||||
|
||||
final class LineMacro extends DynamicStyleMacro {
|
||||
LineMacro(char[] name) {
|
||||
super(name);
|
||||
}
|
||||
public Token execute(MacroExpander expander) {
|
||||
int lineNumber= expander.getCurrentLineNumber();
|
||||
return new TokenWithImage(IToken.tINTEGER, null, 0, 0, Long.toString(lineNumber).toCharArray());
|
||||
}
|
||||
}
|
||||
|
||||
final class TimeMacro extends DynamicStyleMacro {
|
||||
TimeMacro(char[] name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public Token execute(MacroExpander expander) {
|
||||
StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$
|
||||
Calendar cal = Calendar.getInstance();
|
||||
append(buffer, cal.get(Calendar.HOUR_OF_DAY));
|
||||
buffer.append(":"); //$NON-NLS-1$
|
||||
append(buffer, cal.get(Calendar.MINUTE));
|
||||
buffer.append(":"); //$NON-NLS-1$
|
||||
append(buffer, cal.get(Calendar.SECOND));
|
||||
buffer.append("\""); //$NON-NLS-1$
|
||||
return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,15 +32,17 @@ public class SingleMacroExpansionExplorer extends MacroExpansionExplorer {
|
|||
private final CharArrayMap<PreprocessorMacro> fDictionary;
|
||||
private MacroExpansionStep fFullExpansion;
|
||||
private int fExpansionCount;
|
||||
private String fFilePath;
|
||||
private int fLineNumber;
|
||||
|
||||
public SingleMacroExpansionExplorer(String input, IASTName ref, IASTName[] implicitRefs) {
|
||||
public SingleMacroExpansionExplorer(String input, IASTName ref, IASTName[] implicitRefs, String filePath, int lineNumber) {
|
||||
fInput= input;
|
||||
fDictionary= createDictionary(ref, implicitRefs);
|
||||
fFilePath= filePath;
|
||||
fLineNumber= lineNumber;
|
||||
}
|
||||
|
||||
private CharArrayMap<PreprocessorMacro> createDictionary(IASTName ref, IASTName[] implicitRefs) {
|
||||
// mstodo handle dynamic style macros
|
||||
// mstodo clone index-macros
|
||||
CharArrayMap<PreprocessorMacro> map= new CharArrayMap<PreprocessorMacro>(implicitRefs.length+1);
|
||||
addMacroDefinition(map, ref);
|
||||
for (IASTName name : implicitRefs) {
|
||||
|
@ -71,7 +73,7 @@ public class SingleMacroExpansionExplorer extends MacroExpansionExplorer {
|
|||
private void computeExpansion() {
|
||||
MacroExpander expander= new MacroExpander(ILexerLog.NULL, fDictionary, null, LEX_OPTIONS);
|
||||
MacroExpansionTracker tracker= new MacroExpansionTracker(Integer.MAX_VALUE);
|
||||
expander.expand(fInput, tracker);
|
||||
expander.expand(fInput, tracker, fFilePath, fLineNumber);
|
||||
|
||||
fExpansionCount= tracker.getStepCount();
|
||||
ReplaceEdit r= tracker.getReplacement();
|
||||
|
@ -87,7 +89,7 @@ public class SingleMacroExpansionExplorer extends MacroExpansionExplorer {
|
|||
}
|
||||
MacroExpander expander= new MacroExpander(ILexerLog.NULL, fDictionary, null, LEX_OPTIONS);
|
||||
MacroExpansionTracker tracker= new MacroExpansionTracker(step);
|
||||
expander.expand(fInput, tracker);
|
||||
expander.expand(fInput, tracker, fFilePath, fLineNumber);
|
||||
|
||||
fExpansionCount= tracker.getStepCount();
|
||||
ReplaceEdit r= tracker.getReplacement();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
||||
* Copyright (c) 2007, 2008 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
|
||||
|
@ -121,4 +121,8 @@ class TokenList {
|
|||
fLast= l;
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
fFirst= fLast= null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ public class PDOMMacro implements IIndexMacro, IASTFileLocation {
|
|||
fExpansion= getExpansionInDB().getChars();
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
fExpansion= new char[] { ' ' };
|
||||
fExpansion= new char[] {};
|
||||
}
|
||||
}
|
||||
return fExpansion;
|
||||
|
|
Loading…
Add table
Reference in a new issue