1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Patch for Andrew Niefer:

- Fixed Bug36316 Parser/Scanner in infinite loop
This commit is contained in:
Doug Schaefer 2003-04-11 21:20:16 +00:00
parent 080e040924
commit 0c47e3bed5
5 changed files with 299 additions and 177 deletions

View file

@ -0,0 +1,130 @@
/*******************************************************************************
* Copyright (c) 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* IBM Corp. - Rational Software - initial implementation
******************************************************************************/
package org.eclipse.cdt.internal.core.parser;
import java.io.IOException;
import java.io.Reader;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import java.util.Stack;
/**
* @author aniefer
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class ContextStack {
public ContextStack(){
super();
}
public void updateContext(Reader reader, String filename, int type) throws ScannerException {
undoStack.clear();
push( new ScannerContext().initialize(reader, filename, type ) );
}
protected void push( IScannerContext context ) throws ScannerException
{
if( context.getKind() == IScannerContext.INCLUSION )
{
if( !inclusions.add( context.getFilename() ) )
throw new ScannerException( "Inclusion " + context.getFilename() + " already encountered." );
} else if( context.getKind() == IScannerContext.MACROEXPANSION )
{
if( !defines.add( context.getFilename() ) )
throw new ScannerException( "Define " + context.getFilename() + " already encountered." );
}
if( currentContext != null )
contextStack.push(currentContext);
currentContext = context;
}
public boolean rollbackContext() {
try {
currentContext.getReader().close();
} catch (IOException ie) {
System.out.println("Error closing reader");
}
if( currentContext.getKind() == IScannerContext.INCLUSION )
{
inclusions.remove( currentContext.getFilename() );
} else if( currentContext.getKind() == IScannerContext.MACROEXPANSION )
{
defines.remove( currentContext.getFilename() );
}
undoStack.addFirst( currentContext );
if (contextStack.isEmpty()) {
currentContext = null;
return false;
}
currentContext = (ScannerContext) contextStack.pop();
return true;
}
public void undoRollback( IScannerContext undoTo ) throws ScannerException {
if( currentContext == undoTo ){
return;
}
int size = undoStack.size();
if( size > 0 )
{
Iterator iter = undoStack.iterator();
for( int i = size; i > 0; i-- )
{
push( (IScannerContext) undoStack.removeFirst() );
if( currentContext == undoTo )
break;
}
}
}
/**
*
* @param symbol
* @return boolean, whether or not we should expand this definition
*
* 16.3.4-2 If the name of the macro being replaced is found during
* this scan of the replacement list it is not replaced. Further, if
* any nested replacements encounter the name of the macro being replaced,
* it is not replaced.
*/
protected boolean shouldExpandDefinition( String symbol )
{
return !defines.contains( symbol );
}
public IScannerContext getCurrentContext(){
return currentContext;
}
private IScannerContext currentContext;
private Stack contextStack = new Stack();
private LinkedList undoStack = new LinkedList();
private Set inclusions = new HashSet();
private Set defines = new HashSet();
}

View file

@ -18,12 +18,9 @@ import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;
@ -40,18 +37,21 @@ public class Scanner implements IScanner {
}
protected void init(Reader reader, String filename) {
// this is a hack to get around a sudden EOF experience
contextStack.push(
new ScannerContext().initialize(
new StringReader("\n"),
START,
ScannerContext.SENTINEL));
if (filename == null)
currentContext =
new ScannerContext().initialize(reader, TEXT, ScannerContext.TOP );
else
currentContext =
new ScannerContext().initialize(reader, filename, ScannerContext.TOP );
try {
//this is a hack to get around a sudden EOF experience
contextStack.push(
new ScannerContext().initialize(
new StringReader("\n"),
START,
ScannerContext.SENTINEL));
if (filename == null)
contextStack.push( new ScannerContext().initialize(reader, TEXT, ScannerContext.TOP ) );
else
contextStack.push( new ScannerContext().initialize(reader, filename, ScannerContext.TOP ) );
} catch( ScannerException se ) {
//won't happen since we aren't adding an include or a macro
}
}
public Scanner() {
@ -62,42 +62,7 @@ public class Scanner implements IScanner {
definitions = defns;
}
protected void updateContext(Reader reader, String filename, int type) throws ScannerException {
if( type == IScannerContext.INCLUSION )
{
if( !inclusions.add( filename ) )
throw new ScannerException( "Inclusion " + filename + " already encountered." );
System.out.println( "Handle inclusion - " + filename );
}
contextStack.push(currentContext);
currentContext =
new ScannerContext().initialize(reader, filename, type );
}
protected boolean rollbackContext() {
try {
currentContext.getReader().close();
} catch (IOException ie) {
System.out.println("Error closing reader");
}
if( currentContext.getKind() == IScannerContext.INCLUSION )
{
inclusions.remove( currentContext.getFilename() );
System.out.println( "Completed inclusion - " + currentContext.getFilename() );
}
if (contextStack.isEmpty()) {
currentContext = null;
return false;
}
currentContext = (ScannerContext) contextStack.pop();
return true;
}
public void addIncludePath(String includePath) {
includePathNames.add(includePath);
@ -137,7 +102,7 @@ public class Scanner implements IScanner {
return includePathNames.toArray();
}
protected boolean skipOverWhitespace() {
protected boolean skipOverWhitespace() throws ScannerException {
int c = getChar();
boolean result = false;
while ((c != NOCHAR) && ((c == ' ') || (c == '\t')))
@ -233,7 +198,7 @@ public class Scanner implements IScanner {
return currentToken;
}
protected String getNextIdentifier() {
protected String getNextIdentifier() throws ScannerException {
StringBuffer buffer = new StringBuffer();
skipOverWhitespace();
int c = getChar();
@ -275,7 +240,7 @@ public class Scanner implements IScanner {
try {
FileReader inclusionReader =
new FileReader(includeFile);
updateContext(inclusionReader, newPath, ScannerContext.INCLUSION );
contextStack.updateContext(inclusionReader, newPath, ScannerContext.INCLUSION );
return;
} catch (FileNotFoundException fnf) {
// do nothing - check the next directory
@ -286,7 +251,7 @@ public class Scanner implements IScanner {
}
else // local inclusion
{
String currentFilename = currentContext.getFilename();
String currentFilename = contextStack.getCurrentContext().getFilename();
File currentIncludeFile = new File( currentFilename );
String parentDirectory = currentIncludeFile.getParent();
currentIncludeFile = null;
@ -296,7 +261,7 @@ public class Scanner implements IScanner {
try {
FileReader inclusionReader =
new FileReader(includeFile);
updateContext(inclusionReader, fullPath, ScannerContext.INCLUSION );
contextStack.updateContext(inclusionReader, fullPath, ScannerContext.INCLUSION );
return;
} catch (FileNotFoundException fnf) {
if (throwExceptionOnInclusionNotFound)
@ -321,14 +286,14 @@ public class Scanner implements IScanner {
private static final String DEFINED = "defined";
private static final String POUND_DEFINE = "#define ";
private IScannerContext currentContext;
private Stack contextStack = new Stack();
private ContextStack contextStack = new ContextStack();
private IScannerContext lastContext = null;
private List includePathNames = new ArrayList();
private List includePaths = new ArrayList();
private Hashtable definitions = new Hashtable();
private StringBuffer storageBuffer = null;
private Set inclusions = new HashSet();
private int count = 0;
private static HashMap keywords = new HashMap();
private static HashMap ppDirectives = new HashMap();
@ -367,7 +332,10 @@ public class Scanner implements IScanner {
private int getChar( boolean insideString ) {
int c = NOCHAR;
if (currentContext == null)
lastContext = contextStack.getCurrentContext();
if (contextStack.getCurrentContext() == null)
// past the end of file
return c;
@ -375,13 +343,13 @@ public class Scanner implements IScanner {
do {
done = true;
if (currentContext.undoStackSize() != 0 ) {
c = currentContext.popUndo();
if (contextStack.getCurrentContext().undoStackSize() != 0 ) {
c = contextStack.getCurrentContext().popUndo();
} else {
try {
c = currentContext.read();
c = contextStack.getCurrentContext().read();
if (c == NOCHAR) {
if (rollbackContext() == false) {
if (contextStack.rollbackContext() == false) {
c = NOCHAR;
break;
} else {
@ -389,7 +357,7 @@ public class Scanner implements IScanner {
}
}
} catch (IOException e) {
if (rollbackContext() == false) {
if (contextStack.rollbackContext() == false) {
c = NOCHAR;
} else {
done = false;
@ -413,13 +381,14 @@ public class Scanner implements IScanner {
return c;
}
private void ungetChar(int c) {
private void ungetChar(int c) throws ScannerException{
// Should really check whether there already is a char there
// If so, we should be using a buffer, instead of a single char
currentContext.pushUndo(c);
contextStack.getCurrentContext().pushUndo(c);
contextStack.undoRollback( lastContext );
}
protected boolean lookAheadForTokenPasting()
protected boolean lookAheadForTokenPasting() throws ScannerException
{
int c = getChar();
if( c == '#' )
@ -526,7 +495,7 @@ public class Scanner implements IScanner {
return newToken(
type,
buff.toString(),
currentContext);
contextStack.getCurrentContext());
} else {
if (throwExceptionOnUnboundedString)
@ -563,9 +532,11 @@ public class Scanner implements IScanner {
Object mapping = definitions.get(ident);
if (mapping != null) {
expandDefinition(ident, mapping);
c = getChar();
continue;
if( contextStack.shouldExpandDefinition( POUND_DEFINE + ident ) ) {
expandDefinition(ident, mapping);
c = getChar();
continue;
}
}
Object tokenTypeObject = keywords.get(ident);
@ -590,7 +561,7 @@ public class Scanner implements IScanner {
if( storageBuffer != null )
{
storageBuffer.append( ident );
updateContext( new StringReader( storageBuffer.toString()), PASTING, IScannerContext.MACROEXPANSION );
contextStack.updateContext( new StringReader( storageBuffer.toString()), PASTING, IScannerContext.MACROEXPANSION );
storageBuffer = null;
c = getChar();
continue;
@ -598,7 +569,7 @@ public class Scanner implements IScanner {
}
}
return newToken(tokenType, ident, currentContext);
return newToken(tokenType, ident, contextStack.getCurrentContext());
} else if ((c >= '0') && (c <= '9') || c == '.' ) {
StringBuffer buff;
@ -625,10 +596,10 @@ public class Scanner implements IScanner {
if( ! firstCharZero && floatingPoint )
{
ungetChar( c );
return newToken( Token.tDOT, ".", currentContext );
return newToken( Token.tDOT, ".", contextStack.getCurrentContext() );
}
else if( ! firstCharZero )
throw new ScannerException( "Invalid Hexidecimal @ offset " + currentContext.getOffset() );
throw new ScannerException( "Invalid Hexidecimal @ offset " + contextStack.getCurrentContext().getOffset() );
hex = true;
c = getChar();
@ -647,7 +618,7 @@ public class Scanner implements IScanner {
if( floatingPoint || hex ) {
if( buff.toString().equals( "..") && getChar() == '.' )
return newToken( Token.tELIPSE, "..." );
throw new ScannerException( "Invalid floating point @ offset " + currentContext.getOffset() );
throw new ScannerException( "Invalid floating point @ offset " + contextStack.getCurrentContext().getOffset() );
}
floatingPoint = true;
@ -705,7 +676,7 @@ public class Scanner implements IScanner {
{
if( storageBuffer != null )
{
updateContext( new StringReader( buff.toString()), PASTING, IScannerContext.MACROEXPANSION );
contextStack.updateContext( new StringReader( buff.toString()), PASTING, IScannerContext.MACROEXPANSION );
storageBuffer = null;
c = getChar();
continue;
@ -724,10 +695,10 @@ public class Scanner implements IScanner {
return newToken(
tokenType,
result,
currentContext);
contextStack.getCurrentContext());
} else if (c == '#') {
int beginningOffset = currentContext.getOffset() - 1;
int beginningOffset = contextStack.getCurrentContext().getOffset() - 1;
// lets prepare for a preprocessor statement
StringBuffer buff = new StringBuffer();
buff.append((char) c);
@ -740,7 +711,7 @@ public class Scanner implements IScanner {
if( c == '#' )
{
if( skipped )
throw new ScannerException(BAD_PP + currentContext.getOffset());
throw new ScannerException(BAD_PP + contextStack.getCurrentContext().getOffset());
else
return newToken( tPOUNDPOUND, "##" );
}
@ -758,7 +729,7 @@ public class Scanner implements IScanner {
if (directive == null) {
if (throwExceptionOnBadPreprocessorSyntax)
throw new ScannerException(
BAD_PP + currentContext.getOffset());
BAD_PP + contextStack.getCurrentContext().getOffset());
} else {
@ -832,7 +803,7 @@ public class Scanner implements IScanner {
case PreprocessorDirectives.ENDIF :
String restOfLine = getRestOfPreprocessorLine().trim();
if( ! restOfLine.equals( "" ) && throwExceptionOnBadPreprocessorSyntax )
throw new ScannerException( BAD_PP + currentContext.getOffset() );
throw new ScannerException( BAD_PP + contextStack.getCurrentContext().getOffset() );
passOnToClient = branches.poundendif();
c = getChar();
continue;
@ -905,7 +876,7 @@ public class Scanner implements IScanner {
if (!remainderOfLine.equals("")) {
if (throwExceptionOnBadPreprocessorSyntax)
throw new ScannerException(
BAD_PP + currentContext.getOffset());
BAD_PP + contextStack.getCurrentContext().getOffset());
}
c = getChar();
@ -913,7 +884,7 @@ public class Scanner implements IScanner {
default :
if (throwExceptionOnBadPreprocessorSyntax)
throw new ScannerException(
BAD_PP + currentContext.getOffset());
BAD_PP + contextStack.getCurrentContext().getOffset());
}
}
@ -923,10 +894,10 @@ public class Scanner implements IScanner {
c = getChar();
int next = getChar();
if( next == '\'' )
return newToken( Token.tCHAR, new Character( (char)c ).toString(), currentContext );
return newToken( Token.tCHAR, new Character( (char)c ).toString(), contextStack.getCurrentContext() );
else
if( throwExceptionOnBadCharacterRead )
throw new ScannerException( "Invalid character '" + (char)c + "' read @ offset " + currentContext.getOffset() + " of file " + currentContext.getFilename() );
throw new ScannerException( "Invalid character '" + (char)c + "' read @ offset " + contextStack.getCurrentContext().getOffset() + " of file " + contextStack.getCurrentContext().getFilename() );
case ':' :
c = getChar();
switch (c) {
@ -934,32 +905,32 @@ public class Scanner implements IScanner {
return newToken(
Token.tCOLONCOLON,
"::",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tCOLON,
":",
currentContext);
contextStack.getCurrentContext());
}
case ';' :
return newToken(Token.tSEMI, ";", currentContext);
return newToken(Token.tSEMI, ";", contextStack.getCurrentContext());
case ',' :
return newToken(Token.tCOMMA, ",", currentContext);
return newToken(Token.tCOMMA, ",", contextStack.getCurrentContext());
case '?' :
return newToken(Token.tQUESTION, "?", currentContext);
return newToken(Token.tQUESTION, "?", contextStack.getCurrentContext());
case '(' :
return newToken(Token.tLPAREN, "(", currentContext);
return newToken(Token.tLPAREN, "(", contextStack.getCurrentContext());
case ')' :
return newToken(Token.tRPAREN, ")", currentContext);
return newToken(Token.tRPAREN, ")", contextStack.getCurrentContext());
case '[' :
return newToken(Token.tLBRACKET, "[", currentContext);
return newToken(Token.tLBRACKET, "[", contextStack.getCurrentContext());
case ']' :
return newToken(Token.tRBRACKET, "]", currentContext);
return newToken(Token.tRBRACKET, "]", contextStack.getCurrentContext());
case '{' :
return newToken(Token.tLBRACE, "{", currentContext);
return newToken(Token.tLBRACE, "{", contextStack.getCurrentContext());
case '}' :
return newToken(Token.tRBRACE, "}", currentContext);
return newToken(Token.tRBRACE, "}", contextStack.getCurrentContext());
case '+' :
c = getChar();
switch (c) {
@ -967,18 +938,18 @@ public class Scanner implements IScanner {
return newToken(
Token.tPLUSASSIGN,
"+=",
currentContext);
contextStack.getCurrentContext());
case '+' :
return newToken(
Token.tINCR,
"++",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tPLUS,
"+",
currentContext);
contextStack.getCurrentContext());
}
case '-' :
c = getChar();
@ -987,12 +958,12 @@ public class Scanner implements IScanner {
return newToken(
Token.tMINUSASSIGN,
"-=",
currentContext);
contextStack.getCurrentContext());
case '-' :
return newToken(
Token.tDECR,
"--",
currentContext);
contextStack.getCurrentContext());
case '>' :
c = getChar();
switch (c) {
@ -1000,20 +971,20 @@ public class Scanner implements IScanner {
return newToken(
Token.tARROWSTAR,
"->*",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tARROW,
"->",
currentContext);
contextStack.getCurrentContext());
}
default :
ungetChar(c);
return newToken(
Token.tMINUS,
"-",
currentContext);
contextStack.getCurrentContext());
}
case '*' :
c = getChar();
@ -1022,13 +993,13 @@ public class Scanner implements IScanner {
return newToken(
Token.tSTARASSIGN,
"*=",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tSTAR,
"*",
currentContext);
contextStack.getCurrentContext());
}
case '%' :
c = getChar();
@ -1037,13 +1008,13 @@ public class Scanner implements IScanner {
return newToken(
Token.tMODASSIGN,
"%=",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tMOD,
"%",
currentContext);
contextStack.getCurrentContext());
}
case '^' :
c = getChar();
@ -1052,13 +1023,13 @@ public class Scanner implements IScanner {
return newToken(
Token.tXORASSIGN,
"^=",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tXOR,
"^",
currentContext);
contextStack.getCurrentContext());
}
case '&' :
c = getChar();
@ -1067,18 +1038,18 @@ public class Scanner implements IScanner {
return newToken(
Token.tAMPERASSIGN,
"&=",
currentContext);
contextStack.getCurrentContext());
case '&' :
return newToken(
Token.tAND,
"&&",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tAMPER,
"&",
currentContext);
contextStack.getCurrentContext());
}
case '|' :
c = getChar();
@ -1087,21 +1058,21 @@ public class Scanner implements IScanner {
return newToken(
Token.tBITORASSIGN,
"|=",
currentContext);
contextStack.getCurrentContext());
case '|' :
return newToken(
Token.tOR,
"||",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tBITOR,
"|",
currentContext);
contextStack.getCurrentContext());
}
case '~' :
return newToken(Token.tCOMPL, "~", currentContext);
return newToken(Token.tCOMPL, "~", contextStack.getCurrentContext());
case '!' :
c = getChar();
switch (c) {
@ -1109,13 +1080,13 @@ public class Scanner implements IScanner {
return newToken(
Token.tNOTEQUAL,
"!=",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tNOT,
"!",
currentContext);
contextStack.getCurrentContext());
}
case '=' :
c = getChar();
@ -1124,13 +1095,13 @@ public class Scanner implements IScanner {
return newToken(
Token.tEQUAL,
"==",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tASSIGN,
"=",
currentContext);
contextStack.getCurrentContext());
}
case '<' :
c = getChar();
@ -1142,22 +1113,22 @@ public class Scanner implements IScanner {
return newToken(
Token.tSHIFTLASSIGN,
"<<=",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tSHIFTL,
"<<",
currentContext);
contextStack.getCurrentContext());
}
case '=' :
return newToken(
Token.tLTEQUAL,
"<=",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(Token.tLT, "<", currentContext);
return newToken(Token.tLT, "<", contextStack.getCurrentContext());
}
case '>' :
c = getChar();
@ -1169,22 +1140,22 @@ public class Scanner implements IScanner {
return newToken(
Token.tSHIFTRASSIGN,
">>=",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tSHIFTR,
">>",
currentContext);
contextStack.getCurrentContext());
}
case '=' :
return newToken(
Token.tGTEQUAL,
">=",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(Token.tGT, ">", currentContext);
return newToken(Token.tGT, ">", contextStack.getCurrentContext());
}
case '.' :
c = getChar();
@ -1196,7 +1167,7 @@ public class Scanner implements IScanner {
return newToken(
Token.tELIPSE,
"...",
currentContext);
contextStack.getCurrentContext());
default :
break;
}
@ -1205,13 +1176,13 @@ public class Scanner implements IScanner {
return newToken(
Token.tDOTSTAR,
".*",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tDOT,
".",
currentContext);
contextStack.getCurrentContext());
}
break;
case '/' :
@ -1230,18 +1201,18 @@ public class Scanner implements IScanner {
return newToken(
Token.tDIVASSIGN,
"/=",
currentContext);
contextStack.getCurrentContext());
default :
ungetChar(c);
return newToken(
Token.tDIV,
"/",
currentContext);
contextStack.getCurrentContext());
}
default :
// Bad character
if( throwExceptionOnBadCharacterRead )
throw new ScannerException( "Invalid character '" + (char)c + "' read @ offset " + currentContext.getOffset() + " of file " + currentContext.getFilename() );
throw new ScannerException( "Invalid character '" + (char)c + "' read @ offset " + contextStack.getCurrentContext().getOffset() + " of file " + contextStack.getCurrentContext().getFilename() );
else
{
c = ' ';
@ -1509,7 +1480,7 @@ public class Scanner implements IScanner {
{
if( callback != null )
{
offset = currentContext.getOffset() - f.length() - 1; // -1 for the end quote
offset = contextStack.getCurrentContext().getOffset() - f.length() - 1; // -1 for the end quote
callback.inclusionBegin( f, offset, beginningOffset );
callback.inclusionEnd();
@ -1523,7 +1494,7 @@ public class Scanner implements IScanner {
skipOverWhitespace();
// definition
String key = getNextIdentifier();
int offset = currentContext.getOffset() - key.length() - currentContext.undoStackSize();
int offset = contextStack.getCurrentContext().getOffset() - key.length() - contextStack.getCurrentContext().undoStackSize();
if (!quickScan) {
String checkForRedefinition = (String) definitions.get(key);
@ -1617,24 +1588,24 @@ public class Scanner implements IScanner {
// it is a bad statement
if (throwExceptionOnBadPreprocessorSyntax)
throw new ScannerException(
BAD_PP + currentContext.getOffset());
BAD_PP + contextStack.getCurrentContext().getOffset());
}
} else {
System.out.println("Unexpected character " + ((char) c));
if (throwExceptionOnBadPreprocessorSyntax)
throw new ScannerException(BAD_PP + currentContext.getOffset());
throw new ScannerException(BAD_PP + contextStack.getCurrentContext().getOffset());
}
// call the callback accordingly
if( callback != null )
callback.macro( key, offset, beginning, currentContext.getOffset() );
callback.macro( key, offset, beginning, contextStack.getCurrentContext().getOffset() );
}
protected void expandDefinition(String symbol, Object expansion)
throws ScannerException {
if (expansion instanceof String ) {
String replacementValue = (String) expansion;
updateContext( new StringReader(replacementValue), (POUND_DEFINE + symbol ), ScannerContext.MACROEXPANSION );
contextStack.updateContext( new StringReader(replacementValue), (POUND_DEFINE + symbol ), ScannerContext.MACROEXPANSION );
} else if (expansion instanceof IMacroDescriptor ) {
IMacroDescriptor macro = (IMacroDescriptor) expansion;
skipOverWhitespace();
@ -1710,7 +1681,7 @@ public class Scanner implements IScanner {
buffer.append( " " );
}
String finalString = buffer.toString();
updateContext(
contextStack.updateContext(
new StringReader(finalString),
POUND_DEFINE + macro.getSignature(), ScannerContext.MACROEXPANSION );
} else

View file

@ -1,3 +1,8 @@
2003-04-11 Andrew Niefer
Moved ScannerFailedTest::testBug36316 to ScannerTestCase::testBug36316
Added ScannerFailedTest::testBug36047
Added ScannerTestCase::testNestedRecursiveDefines
2003-04-10 John Camelon
Added DOMTests::testBug36237().

View file

@ -11,11 +11,14 @@
package org.eclipse.cdt.core.parser.failedTests;
import java.io.StringWriter;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.parser.tests.ScannerTestCase;
import org.eclipse.cdt.internal.core.parser.ScannerException;
import org.eclipse.cdt.internal.core.parser.Token;
/**
@ -34,29 +37,34 @@ public class ScannerFailedTest extends ScannerTestCase {
{
TestSuite suite = new TestSuite();
suite.addTest( new ScannerFailedTest( "testBug36316" ) );
suite.addTest( new ScannerFailedTest( "testBug36047" ) );
return suite;
}
public void testBug36316() throws Exception
public void testBug36047() throws Exception
{
boolean testPassed = false;
try
{
initializeScanner( "#define A B->A\nA" );
StringWriter writer = new StringWriter();
writer.write( "# define MAD_VERSION_STRINGIZE(str) #str\n" );
writer.write( "# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num)\n" );
writer.write( "# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) \".\"\n" );
initializeScanner( writer.toString() );
validateEOF();
testPassed = true;
validateIdentifier("B");
validateDefinition("A", "B->A");
validateToken(Token.tARROW);
validateIdentifier("A");
validateEOF();
fail( "This test was expected to fail." );
} catch( Throwable e )
{
if( !( e instanceof AssertionFailedError ) ){
fail( "Unexpected failure" );
}
}
catch( ScannerException se )
{
if( !se.getMessage().equals( "Invalid preprocessor directive encountered at offset 5" ) ){
fail( "Unexpected Error: " + se.getMessage() );
}
}
if( testPassed )
fail( "The expected error did not occur." );
}
}

View file

@ -1192,23 +1192,6 @@ public class ScannerTestCase extends TestCase
}
}
// public void testBug36047()
// {
// try
// {
// StringWriter writer = new StringWriter();
// writer.write( "# define MAD_VERSION_STRINGIZE(str) #str\n" );
// writer.write( "# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num)\n" );
// writer.write( "# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) \".\"\n" );
// initializeScanner( writer.toString() );
// validateEOF();
// }
// catch( ScannerException se )
// {
// fail( EXCEPTION_THROWN + se.toString() );
// }
// }
public void testBug36045() throws Exception
{
StringBuffer buffer = new StringBuffer();
@ -1294,4 +1277,29 @@ public class ScannerTestCase extends TestCase
fail(EXCEPTION_THROWN + se.toString());
}
}
public void testNestedRecursiveDefines() throws Exception
{
initializeScanner( "#define C B A\n#define B C C\n#define A B\nA" );
validateIdentifier("B");
validateDefinition("A", "B");
validateDefinition("B", "C C");
validateDefinition("C", "B A");
validateIdentifier("A");
validateIdentifier("B");
validateIdentifier("A");
validateEOF();
}
public void testBug36316() throws Exception
{
initializeScanner( "#define A B->A\nA" );
validateIdentifier("B");
validateDefinition("A", "B->A");
validateToken(Token.tARROW);
validateIdentifier("A");
validateEOF();
}
}