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

View file

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