mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-09 10:46:02 +02:00
Patch for John Camelon:
- added in support for detecting and reporting circular inclusions - added optimization by caching inclusion directories - added macro pasting capabilities and tests - updated inclusion searching algorithm for local inclusions
This commit is contained in:
parent
1741944fb0
commit
2626b7316b
5 changed files with 343 additions and 128 deletions
|
@ -1,6 +1,6 @@
|
||||||
package org.eclipse.cdt.internal.core.parser;
|
package org.eclipse.cdt.internal.core.parser;
|
||||||
import java.io.Reader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
/**
|
/**
|
||||||
* @author jcamelon
|
* @author jcamelon
|
||||||
*
|
*
|
||||||
|
@ -11,11 +11,24 @@ import java.io.IOException;
|
||||||
* Window>Preferences>Java>Code Generation.
|
* Window>Preferences>Java>Code Generation.
|
||||||
*/
|
*/
|
||||||
public interface IScannerContext {
|
public interface IScannerContext {
|
||||||
IScannerContext initialize(Reader r, String f, int u);
|
|
||||||
|
public static int SENTINEL = 0;
|
||||||
|
public static int TOP = 1;
|
||||||
|
public static int INCLUSION = 2;
|
||||||
|
public static int MACROEXPANSION = 3;
|
||||||
|
|
||||||
|
|
||||||
|
IScannerContext initialize(Reader r, String f, int k);
|
||||||
int read() throws IOException;
|
int read() throws IOException;
|
||||||
String getFilename();
|
String getFilename();
|
||||||
int getOffset();
|
int getOffset();
|
||||||
Reader getReader();
|
Reader getReader();
|
||||||
int getUndo();
|
|
||||||
void setUndo(int undo);
|
int undoStackSize();
|
||||||
|
int popUndo();
|
||||||
|
void pushUndo(int undo);
|
||||||
|
|
||||||
|
|
||||||
|
int getKind();
|
||||||
|
void setKind( int kind );
|
||||||
}
|
}
|
|
@ -10,6 +10,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.parser;
|
package org.eclipse.cdt.internal.core.parser;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -17,9 +18,11 @@ 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.Stack;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
@ -46,13 +49,13 @@ public class Scanner implements IScanner {
|
||||||
new ScannerContext().initialize(
|
new ScannerContext().initialize(
|
||||||
new StringReader("\n"),
|
new StringReader("\n"),
|
||||||
START,
|
START,
|
||||||
NOCHAR));
|
ScannerContext.SENTINEL));
|
||||||
if (filename == null)
|
if (filename == null)
|
||||||
currentContext =
|
currentContext =
|
||||||
new ScannerContext().initialize(reader, TEXT, NOCHAR);
|
new ScannerContext().initialize(reader, TEXT, ScannerContext.TOP );
|
||||||
else
|
else
|
||||||
currentContext =
|
currentContext =
|
||||||
new ScannerContext().initialize(reader, filename, NOCHAR);
|
new ScannerContext().initialize(reader, filename, ScannerContext.TOP );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Scanner() {
|
public Scanner() {
|
||||||
|
@ -63,13 +66,19 @@ public class Scanner implements IScanner {
|
||||||
definitions = defns;
|
definitions = defns;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateContext(Reader reader, String filename) {
|
protected void updateContext(Reader reader, String filename, int type) throws ScannerException {
|
||||||
// if (callback != null)
|
if( type == IScannerContext.INCLUSION )
|
||||||
// callback.inclusionBegin(filename); // not quite right ... fix me!!!
|
{
|
||||||
|
if( !inclusions.add( filename ) )
|
||||||
|
throw new ScannerException( "Inclusion " + filename + " already encountered." );
|
||||||
|
|
||||||
|
System.out.println( "Handle inclusion - " + filename );
|
||||||
|
}
|
||||||
|
|
||||||
contextStack.push(currentContext);
|
contextStack.push(currentContext);
|
||||||
currentContext =
|
currentContext =
|
||||||
new ScannerContext().initialize(reader, filename, NOCHAR);
|
new ScannerContext().initialize(reader, filename, type );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean rollbackContext() {
|
protected boolean rollbackContext() {
|
||||||
|
@ -79,26 +88,41 @@ public class Scanner implements IScanner {
|
||||||
System.out.println("Error closing reader");
|
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()) {
|
if (contextStack.isEmpty()) {
|
||||||
currentContext = null;
|
currentContext = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (callback != null)
|
|
||||||
// callback.inclusionEnd();
|
|
||||||
|
|
||||||
currentContext = (ScannerContext) contextStack.pop();
|
currentContext = (ScannerContext) contextStack.pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addIncludePath(String includePath) {
|
public void addIncludePath(String includePath) {
|
||||||
includePaths.add(includePath);
|
includePathNames.add(includePath);
|
||||||
|
includePaths.add( new File( includePath ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void overwriteIncludePath(List newIncludePaths) {
|
public void overwriteIncludePath(List newIncludePaths) {
|
||||||
includePaths = null;
|
includePathNames = null;
|
||||||
includePaths = new ArrayList();
|
includePaths = null;
|
||||||
includePaths.addAll(newIncludePaths);
|
includePathNames = new ArrayList();
|
||||||
|
includePaths = new ArrayList();
|
||||||
|
includePathNames.addAll(newIncludePaths);
|
||||||
|
|
||||||
|
Iterator i = includePathNames.iterator();
|
||||||
|
while( i.hasNext() )
|
||||||
|
{
|
||||||
|
String path = (String) i.next();
|
||||||
|
includePaths.add( new File( path ));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDefinition(String key, IMacroDescriptor macro) {
|
public void addDefinition(String key, IMacroDescriptor macro) {
|
||||||
|
@ -114,15 +138,20 @@ public class Scanner implements IScanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Object[] getIncludePaths() {
|
public final Object[] getIncludePaths() {
|
||||||
return includePaths.toArray();
|
return includePathNames.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void skipOverWhitespace() {
|
protected boolean skipOverWhitespace() {
|
||||||
int c = getChar();
|
int c = getChar();
|
||||||
|
boolean result = false;
|
||||||
while ((c != NOCHAR) && ((c == ' ') || (c == '\t')))
|
while ((c != NOCHAR) && ((c == ' ') || (c == '\t')))
|
||||||
|
{
|
||||||
c = getChar();
|
c = getChar();
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
if (c != NOCHAR)
|
if (c != NOCHAR)
|
||||||
ungetChar(c);
|
ungetChar(c);
|
||||||
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +221,12 @@ public class Scanner implements IScanner {
|
||||||
currentToken = t;
|
currentToken = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void resetStorageBuffer()
|
||||||
|
{
|
||||||
|
if( storageBuffer != null )
|
||||||
|
storageBuffer = null;
|
||||||
|
}
|
||||||
|
|
||||||
protected Token newToken(int t, String i, IScannerContext c) {
|
protected Token newToken(int t, String i, IScannerContext c) {
|
||||||
setCurrentToken(new Token(t, i, c));
|
setCurrentToken(new Token(t, i, c));
|
||||||
return currentToken;
|
return currentToken;
|
||||||
|
@ -201,7 +236,7 @@ public class Scanner implements IScanner {
|
||||||
setCurrentToken(new Token(t, i));
|
setCurrentToken(new Token(t, i));
|
||||||
return currentToken;
|
return currentToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getNextIdentifier() {
|
protected String getNextIdentifier() {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
skipOverWhitespace();
|
skipOverWhitespace();
|
||||||
|
@ -225,56 +260,81 @@ public class Scanner implements IScanner {
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleInclusion(String fileName) throws ScannerException {
|
protected void handleInclusion(String fileName, boolean useIncludePaths ) throws ScannerException {
|
||||||
// Skip over inclusions in quickScan mode
|
|
||||||
if (quickScan)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// iterate through the include paths
|
if( useIncludePaths ) // search include paths for this file
|
||||||
Iterator iter = includePaths.iterator();
|
{
|
||||||
|
// iterate through the include paths
|
||||||
while (iter.hasNext()) {
|
Iterator iter = includePaths.iterator();
|
||||||
String path = (String) iter.next();
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
java.io.File pathFile = new java.io.File(path);
|
|
||||||
if (pathFile.isDirectory()) {
|
File pathFile = (File)iter.next();
|
||||||
String newPath = pathFile + "\\" + fileName;
|
if (pathFile.isDirectory()) {
|
||||||
|
String newPath = pathFile.getPath() + File.separatorChar + fileName;
|
||||||
java.io.File includeFile = new java.io.File(newPath);
|
|
||||||
|
File includeFile = new File(newPath);
|
||||||
if (includeFile.exists() && includeFile.isFile()) {
|
|
||||||
try {
|
if (includeFile.exists() && includeFile.isFile()) {
|
||||||
FileReader inclusionReader =
|
try {
|
||||||
new FileReader(includeFile);
|
FileReader inclusionReader =
|
||||||
//System.out.println( "Parsing inclusion file " + newPath );
|
new FileReader(includeFile);
|
||||||
updateContext(inclusionReader, newPath);
|
updateContext(inclusionReader, newPath, ScannerContext.INCLUSION );
|
||||||
return;
|
return;
|
||||||
} catch (FileNotFoundException fnf) {
|
} catch (FileNotFoundException fnf) {
|
||||||
// do nothing
|
// do nothing - check the next directory
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else // local inclusion
|
||||||
|
{
|
||||||
|
String currentFilename = currentContext.getFilename();
|
||||||
|
File currentIncludeFile = new File( currentFilename );
|
||||||
|
String parentDirectory = currentIncludeFile.getParent();
|
||||||
|
currentIncludeFile = null;
|
||||||
|
String fullPath = parentDirectory + File.separatorChar + fileName;
|
||||||
|
File includeFile = new File( fullPath );
|
||||||
|
if (includeFile.exists() && includeFile.isFile()) {
|
||||||
|
try {
|
||||||
|
FileReader inclusionReader =
|
||||||
|
new FileReader(includeFile);
|
||||||
|
updateContext(inclusionReader, fullPath, ScannerContext.INCLUSION );
|
||||||
|
return;
|
||||||
|
} catch (FileNotFoundException fnf) {
|
||||||
|
if (throwExceptionOnInclusionNotFound)
|
||||||
|
throw new ScannerException("Cannot find inclusion " + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (throwExceptionOnInclusionNotFound)
|
if (throwExceptionOnInclusionNotFound)
|
||||||
throw new ScannerException("Cannot find inclusion " + fileName);
|
throw new ScannerException("Cannot find inclusion " + fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
public static final int NOCHAR = -1;
|
private static final int NOCHAR = -1;
|
||||||
|
|
||||||
private static final String TEXT = "<text>";
|
private static final String TEXT = "<text>";
|
||||||
private static final String START = "<initial reader>";
|
private static final String START = "<initial reader>";
|
||||||
private static final String EXPRESSION = "<expression>";
|
private static final String EXPRESSION = "<expression>";
|
||||||
|
private static final String PASTING = "<pasting>";
|
||||||
private static final String BAD_PP =
|
private static final String BAD_PP =
|
||||||
"Invalid preprocessor directive encountered at offset ";
|
"Invalid preprocessor directive encountered at offset ";
|
||||||
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 ";
|
||||||
|
|
||||||
|
public static final int tPOUNDPOUND = -6;
|
||||||
|
|
||||||
private IScannerContext currentContext;
|
private IScannerContext currentContext;
|
||||||
private Stack contextStack = new Stack();
|
private Stack contextStack = new Stack();
|
||||||
|
|
||||||
|
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 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();
|
||||||
|
@ -295,7 +355,6 @@ public class Scanner implements IScanner {
|
||||||
private boolean throwExceptionOnUnboundedString = true;
|
private boolean throwExceptionOnUnboundedString = true;
|
||||||
private boolean throwExceptionOnEOFWithinMultilineComment = true;
|
private boolean throwExceptionOnEOFWithinMultilineComment = true;
|
||||||
private boolean throwExceptionOnEOFWithoutBalancedEndifs = true;
|
private boolean throwExceptionOnEOFWithoutBalancedEndifs = true;
|
||||||
private boolean providedDefinedMacro = true;
|
|
||||||
|
|
||||||
private boolean quickScan = false;
|
private boolean quickScan = false;
|
||||||
public void setQuickScan(boolean qs) {
|
public void setQuickScan(boolean qs) {
|
||||||
|
@ -314,9 +373,8 @@ public class Scanner implements IScanner {
|
||||||
do {
|
do {
|
||||||
done = true;
|
done = true;
|
||||||
|
|
||||||
if (currentContext.getUndo() != NOCHAR) {
|
if (currentContext.undoStackSize() != 0 ) {
|
||||||
c = currentContext.getUndo();
|
c = currentContext.popUndo();
|
||||||
currentContext.setUndo(NOCHAR);
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
c = currentContext.read();
|
c = currentContext.read();
|
||||||
|
@ -354,11 +412,40 @@ public class Scanner implements IScanner {
|
||||||
private void ungetChar(int c) {
|
private void ungetChar(int c) {
|
||||||
// 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.setUndo(c);
|
currentContext.pushUndo(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Token nextToken() throws ScannerException {
|
protected boolean lookAheadForTokenPasting()
|
||||||
|
{
|
||||||
|
int c = getChar();
|
||||||
|
if( c == '#' )
|
||||||
|
{
|
||||||
|
c = getChar();
|
||||||
|
if( c == '#' )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ungetChar( c );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ungetChar( c );
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Token nextToken() throws ScannerException {
|
||||||
|
return nextToken( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected Token nextToken( boolean pasting ) throws ScannerException
|
||||||
|
{
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
int c = getChar();
|
int c = getChar();
|
||||||
|
@ -393,12 +480,9 @@ public class Scanner implements IScanner {
|
||||||
|
|
||||||
String ident = buff.toString();
|
String ident = buff.toString();
|
||||||
|
|
||||||
if (providedDefinedMacro) {
|
if (ident.equals(DEFINED))
|
||||||
if (ident.equals(DEFINED)) {
|
return newToken(Token.tINTEGER, handleDefinedMacro());
|
||||||
return newToken(Token.tINTEGER, handleDefinedMacro());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object mapping = definitions.get(ident);
|
Object mapping = definitions.get(ident);
|
||||||
|
|
||||||
if (mapping != null) {
|
if (mapping != null) {
|
||||||
|
@ -412,6 +496,31 @@ public class Scanner implements IScanner {
|
||||||
if (tokenTypeObject != null)
|
if (tokenTypeObject != null)
|
||||||
tokenType = ((Integer) tokenTypeObject).intValue();
|
tokenType = ((Integer) tokenTypeObject).intValue();
|
||||||
|
|
||||||
|
if( pasting )
|
||||||
|
{
|
||||||
|
if( lookAheadForTokenPasting() )
|
||||||
|
{
|
||||||
|
if( storageBuffer == null )
|
||||||
|
storageBuffer = buff;
|
||||||
|
else
|
||||||
|
storageBuffer.append( ident );
|
||||||
|
|
||||||
|
c = getChar();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( storageBuffer != null )
|
||||||
|
{
|
||||||
|
storageBuffer.append( ident );
|
||||||
|
updateContext( new StringReader( storageBuffer.toString()), PASTING, IScannerContext.MACROEXPANSION );
|
||||||
|
storageBuffer = null;
|
||||||
|
c = getChar();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return newToken(tokenType, ident, currentContext);
|
return newToken(tokenType, ident, currentContext);
|
||||||
} else if (c == '"') {
|
} else if (c == '"') {
|
||||||
// string
|
// string
|
||||||
|
@ -436,7 +545,18 @@ public class Scanner implements IScanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ((c >= '0') && (c <= '9')) {
|
} else if ((c >= '0') && (c <= '9')) {
|
||||||
StringBuffer buff = new StringBuffer();
|
StringBuffer buff;
|
||||||
|
|
||||||
|
if( pasting )
|
||||||
|
{
|
||||||
|
if( storageBuffer != null )
|
||||||
|
buff = storageBuffer;
|
||||||
|
else
|
||||||
|
buff = new StringBuffer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buff = new StringBuffer();
|
||||||
|
|
||||||
buff.append((char) c);
|
buff.append((char) c);
|
||||||
|
|
||||||
c = getChar();
|
c = getChar();
|
||||||
|
@ -454,21 +574,52 @@ public class Scanner implements IScanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
ungetChar(c);
|
ungetChar(c);
|
||||||
|
|
||||||
|
if( pasting )
|
||||||
|
{
|
||||||
|
if( lookAheadForTokenPasting() )
|
||||||
|
{
|
||||||
|
storageBuffer = buff;
|
||||||
|
c = getChar();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( storageBuffer != null )
|
||||||
|
{
|
||||||
|
updateContext( new StringReader( buff.toString()), PASTING, IScannerContext.MACROEXPANSION );
|
||||||
|
storageBuffer = null;
|
||||||
|
c = getChar();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return newToken(
|
return newToken(
|
||||||
Token.tINTEGER,
|
Token.tINTEGER,
|
||||||
buff.toString(),
|
buff.toString(),
|
||||||
currentContext);
|
currentContext);
|
||||||
|
|
||||||
} else if (c == '#') {
|
} else if (c == '#') {
|
||||||
// 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);
|
||||||
|
|
||||||
// we are allowed arbitrary whitespace after the '#' and before the rest of the text
|
// we are allowed arbitrary whitespace after the '#' and before the rest of the text
|
||||||
skipOverWhitespace();
|
boolean skipped = skipOverWhitespace();
|
||||||
|
|
||||||
c = getChar();
|
c = getChar();
|
||||||
|
|
||||||
|
if( c == '#' )
|
||||||
|
{
|
||||||
|
if( skipped )
|
||||||
|
throw new ScannerException(BAD_PP + currentContext.getOffset());
|
||||||
|
else
|
||||||
|
return newToken( tPOUNDPOUND, "##" );
|
||||||
|
}
|
||||||
|
|
||||||
while (((c >= 'a') && (c <= 'z'))
|
while (((c >= 'a') && (c <= 'z'))
|
||||||
|| ((c >= 'A') && (c <= 'Z')) | (c == '_')) {
|
|| ((c >= 'A') && (c <= 'Z')) || (c == '_') ) {
|
||||||
buff.append((char) c);
|
buff.append((char) c);
|
||||||
c = getChar();
|
c = getChar();
|
||||||
}
|
}
|
||||||
|
@ -1128,14 +1279,14 @@ public class Scanner implements IScanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (expressionEvalResult.getClass() == java.lang.Integer.class) {
|
if (expressionEvalResult instanceof Integer ) {
|
||||||
int i = ((Integer) expressionEvalResult).intValue();
|
int i = ((Integer) expressionEvalResult).intValue();
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (
|
} else if (
|
||||||
expressionEvalResult.getClass() == java.lang.Boolean.class) {
|
expressionEvalResult instanceof Boolean ) {
|
||||||
return ((Boolean) expressionEvalResult).booleanValue();
|
return ((Boolean) expressionEvalResult).booleanValue();
|
||||||
} else {
|
} else {
|
||||||
throw new ScannerException(
|
throw new ScannerException(
|
||||||
|
@ -1189,6 +1340,7 @@ public class Scanner implements IScanner {
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
StringBuffer fileName = new StringBuffer();
|
StringBuffer fileName = new StringBuffer();
|
||||||
|
boolean useIncludePath = true;
|
||||||
if (c == '<') {
|
if (c == '<') {
|
||||||
c = getChar();
|
c = getChar();
|
||||||
while ((c != '>')) {
|
while ((c != '>')) {
|
||||||
|
@ -1202,7 +1354,7 @@ public class Scanner implements IScanner {
|
||||||
fileName.append((char) c);
|
fileName.append((char) c);
|
||||||
c = getChar();
|
c = getChar();
|
||||||
}
|
}
|
||||||
|
useIncludePath = false;
|
||||||
// TO DO: Make sure the directory of the current file is in the
|
// TO DO: Make sure the directory of the current file is in the
|
||||||
// inclusion paths.
|
// inclusion paths.
|
||||||
}
|
}
|
||||||
|
@ -1220,16 +1372,14 @@ public class Scanner implements IScanner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
handleInclusion(f.trim());
|
handleInclusion(f.trim(), useIncludePath );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void poundDefine() throws ScannerException {
|
protected void poundDefine() throws ScannerException {
|
||||||
skipOverWhitespace();
|
skipOverWhitespace();
|
||||||
// definition
|
// definition
|
||||||
String key = getNextIdentifier();
|
String key = getNextIdentifier();
|
||||||
int offset = currentContext.getOffset() - key.length();
|
int offset = currentContext.getOffset() - key.length() - currentContext.undoStackSize();
|
||||||
if( currentContext.getUndo() != Scanner.NOCHAR )
|
|
||||||
offset -= 1;
|
|
||||||
|
|
||||||
if (throwExceptionOnRedefinition) {
|
if (throwExceptionOnRedefinition) {
|
||||||
String checkForRedefinition = (String) definitions.get(key);
|
String checkForRedefinition = (String) definitions.get(key);
|
||||||
|
@ -1274,11 +1424,11 @@ public class Scanner implements IScanner {
|
||||||
helperScanner.initialize(
|
helperScanner.initialize(
|
||||||
new StringReader(replacementString),
|
new StringReader(replacementString),
|
||||||
null);
|
null);
|
||||||
Token t = helperScanner.nextToken();
|
Token t = helperScanner.nextToken(false);
|
||||||
|
|
||||||
while (t.type != Token.tEOF) {
|
while (t.type != Token.tEOF) {
|
||||||
macroReplacementTokens.add(t);
|
macroReplacementTokens.add(t);
|
||||||
t = helperScanner.nextToken();
|
t = helperScanner.nextToken(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
IMacroDescriptor descriptor = new MacroDescriptor();
|
IMacroDescriptor descriptor = new MacroDescriptor();
|
||||||
|
@ -1295,7 +1445,8 @@ public class Scanner implements IScanner {
|
||||||
|
|
||||||
// get what we are to map the name to and add it to the definitions list
|
// get what we are to map the name to and add it to the definitions list
|
||||||
String value = getRestOfPreprocessorLine();
|
String value = getRestOfPreprocessorLine();
|
||||||
addDefinition(key, value);
|
addDefinition( key, value );
|
||||||
|
|
||||||
} else if (c == '/') {
|
} else if (c == '/') {
|
||||||
// this could be a comment
|
// this could be a comment
|
||||||
c = getChar();
|
c = getChar();
|
||||||
|
@ -1333,12 +1484,10 @@ public class Scanner implements IScanner {
|
||||||
|
|
||||||
protected void expandDefinition(String symbol, Object expansion)
|
protected void expandDefinition(String symbol, Object expansion)
|
||||||
throws ScannerException {
|
throws ScannerException {
|
||||||
if (expansion.getClass() == String.class) {
|
if (expansion instanceof String ) {
|
||||||
String replacementValue = (String) expansion;
|
String replacementValue = (String) expansion;
|
||||||
updateContext(
|
updateContext( new StringReader(replacementValue), (POUND_DEFINE + symbol ), ScannerContext.MACROEXPANSION );
|
||||||
new StringReader(replacementValue),
|
} else if (expansion instanceof IMacroDescriptor ) {
|
||||||
POUND_DEFINE + symbol);
|
|
||||||
} else if (expansion.getClass() == MacroDescriptor.class) {
|
|
||||||
IMacroDescriptor macro = (IMacroDescriptor) expansion;
|
IMacroDescriptor macro = (IMacroDescriptor) expansion;
|
||||||
skipOverWhitespace();
|
skipOverWhitespace();
|
||||||
int c = getChar();
|
int c = getChar();
|
||||||
|
@ -1359,7 +1508,7 @@ public class Scanner implements IScanner {
|
||||||
buffer.append((char) c);
|
buffer.append((char) c);
|
||||||
c = getChar();
|
c = getChar();
|
||||||
}
|
}
|
||||||
String betweenTheBrackets = buffer.toString();
|
String betweenTheBrackets = buffer.toString().trim();
|
||||||
StringTokenizer tokenizer =
|
StringTokenizer tokenizer =
|
||||||
new StringTokenizer(betweenTheBrackets, ",");
|
new StringTokenizer(betweenTheBrackets, ",");
|
||||||
Vector parameterValues = new Vector(tokenizer.countTokens());
|
Vector parameterValues = new Vector(tokenizer.countTokens());
|
||||||
|
@ -1387,30 +1536,40 @@ public class Scanner implements IScanner {
|
||||||
|
|
||||||
// is this identifier in the parameterNames
|
// is this identifier in the parameterNames
|
||||||
// list?
|
// list?
|
||||||
|
|
||||||
int index = parameterNames.indexOf(t.image);
|
int index = parameterNames.indexOf(t.image);
|
||||||
if (index == -1 ) {
|
if (index == -1 ) {
|
||||||
// not found
|
// not found
|
||||||
// just add image to buffer
|
// just add image to buffer
|
||||||
buffer.append(t.image);
|
buffer.append(t.image );
|
||||||
} else {
|
} else {
|
||||||
buffer.append(
|
buffer.append(
|
||||||
(String) parameterValues.elementAt(index));
|
(String) parameterValues.elementAt(index) );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buffer.append(t.image);
|
buffer.append(t.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean pastingNext = false;
|
||||||
|
|
||||||
|
if( i != numberOfTokens - 1)
|
||||||
|
{
|
||||||
|
Token t2 = (Token) tokens.get(i+1);
|
||||||
|
if( t2.getType() == tPOUNDPOUND )
|
||||||
|
pastingNext = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( t.getType() != tPOUNDPOUND && ! pastingNext )
|
||||||
|
buffer.append( " " );
|
||||||
}
|
}
|
||||||
|
String finalString = buffer.toString();
|
||||||
updateContext(
|
updateContext(
|
||||||
new StringReader(buffer.toString()),
|
new StringReader(finalString),
|
||||||
POUND_DEFINE + macro.getSignature());
|
POUND_DEFINE + macro.getSignature(), ScannerContext.MACROEXPANSION );
|
||||||
} else {
|
} else
|
||||||
if (throwExceptionOnBadMacroExpansion)
|
if (throwExceptionOnBadMacroExpansion)
|
||||||
throw new ScannerException(
|
throw new ScannerException(
|
||||||
"Improper use of macro " + symbol);
|
"Improper use of macro " + symbol);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
System.out.println(
|
System.out.println(
|
||||||
"Unexpected class stored in definitions table. "
|
"Unexpected class stored in definitions table. "
|
||||||
|
|
|
@ -12,21 +12,23 @@ package org.eclipse.cdt.internal.core.parser;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
public class ScannerContext implements IScannerContext
|
public class ScannerContext implements IScannerContext
|
||||||
{
|
{
|
||||||
private Reader reader;
|
private Reader reader;
|
||||||
private String filename;
|
private String filename;
|
||||||
private int offset;
|
private int offset;
|
||||||
private int undo;
|
private Stack undo = new Stack();
|
||||||
|
private int kind;
|
||||||
|
|
||||||
public ScannerContext(){}
|
public ScannerContext(){}
|
||||||
public IScannerContext initialize(Reader r, String f, int u )
|
public IScannerContext initialize(Reader r, String f, int k)
|
||||||
{
|
{
|
||||||
reader = r;
|
reader = r;
|
||||||
filename = f;
|
filename = f;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
undo = u;
|
kind = k;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,22 +64,44 @@ public class ScannerContext implements IScannerContext
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final int undoStackSize()
|
||||||
|
{
|
||||||
|
return undo.size();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the undo.
|
* Returns the undo.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public final int getUndo()
|
public final int popUndo()
|
||||||
{
|
{
|
||||||
return undo;
|
return ((Integer)undo.pop()).intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the undo.
|
* Sets the undo.
|
||||||
* @param undo The undo to set
|
* @param undo The undo to set
|
||||||
*/
|
*/
|
||||||
public void setUndo(int undo)
|
public void pushUndo(int undo)
|
||||||
{
|
{
|
||||||
this.undo= undo;
|
this.undo.push( new Integer( undo ));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the kind.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public int getKind() {
|
||||||
|
return kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the kind.
|
||||||
|
* @param kind The kind to set
|
||||||
|
*/
|
||||||
|
public void setKind(int kind) {
|
||||||
|
this.kind = kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,7 @@ public class Token {
|
||||||
type = t;
|
type = t;
|
||||||
image = i;
|
image = i;
|
||||||
filename = context.getFilename();
|
filename = context.getFilename();
|
||||||
offset = context.getOffset() - image.length();
|
offset = context.getOffset() - image.length() - context.undoStackSize();
|
||||||
|
|
||||||
if( context.getUndo() != Scanner.NOCHAR )
|
|
||||||
offset -= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Token(int t, String i) {
|
public Token(int t, String i) {
|
||||||
|
|
|
@ -154,7 +154,6 @@ public class ScannerTestCase extends TestCase
|
||||||
"This statement should not be reached "
|
"This statement should not be reached "
|
||||||
+ "as we sent in bad preprocessor input to the scanner";
|
+ "as we sent in bad preprocessor input to the scanner";
|
||||||
public final static boolean verbose= false;
|
public final static boolean verbose= false;
|
||||||
public final static boolean doConcatenation= false;
|
|
||||||
public final static boolean doIncludeStdio= false;
|
public final static boolean doIncludeStdio= false;
|
||||||
public final static boolean doIncludeWindowsH= false;
|
public final static boolean doIncludeWindowsH= false;
|
||||||
public final static boolean doIncludeWinUserH= false;
|
public final static boolean doIncludeWinUserH= false;
|
||||||
|
@ -349,7 +348,7 @@ public class ScannerTestCase extends TestCase
|
||||||
public void prepareForWindowsRH()
|
public void prepareForWindowsRH()
|
||||||
{
|
{
|
||||||
scanner.addIncludePath(
|
scanner.addIncludePath(
|
||||||
"C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\PlatformSDK\\include");
|
"C:\\Program Files\\Microsoft Visual Studio\\VC98\\Include");
|
||||||
scanner.addDefinition("_WIN32_WINNT", "0x0300");
|
scanner.addDefinition("_WIN32_WINNT", "0x0300");
|
||||||
scanner.addDefinition("WINVER", "0x0400");
|
scanner.addDefinition("WINVER", "0x0400");
|
||||||
scanner.addDefinition("_WIN32_WINDOWS", "0x0300");
|
scanner.addDefinition("_WIN32_WINDOWS", "0x0300");
|
||||||
|
@ -359,51 +358,74 @@ public class ScannerTestCase extends TestCase
|
||||||
public void prepareForWindowsH()
|
public void prepareForWindowsH()
|
||||||
{
|
{
|
||||||
scanner.addIncludePath(
|
scanner.addIncludePath(
|
||||||
"C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\PlatformSDK\\include");
|
"C:\\Program Files\\Microsoft Visual Studio\\VC98\\Include");
|
||||||
scanner.addIncludePath(
|
|
||||||
"C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\include");
|
|
||||||
scanner.addDefinition("_MSC_VER", "1200");
|
scanner.addDefinition("_MSC_VER", "1200");
|
||||||
scanner.addDefinition("__cplusplus", "1");
|
scanner.addDefinition("__cplusplus", "1");
|
||||||
scanner.addDefinition("__STDC__", "1");
|
scanner.addDefinition("__STDC__", "1");
|
||||||
scanner.addDefinition("_WIN32", "");
|
scanner.addDefinition("_WIN32", "");
|
||||||
scanner.addDefinition( "__midl", "1000" );
|
scanner.addDefinition( "__midl", "1000" );
|
||||||
|
scanner.addDefinition("_WIN32_WINNT", "0x0300");
|
||||||
|
scanner.addDefinition("WINVER", "0x0400");
|
||||||
|
scanner.addDefinition( "_M_IX86", "300");
|
||||||
|
scanner.addDefinition( "_INTEGRAL_MAX_BITS", "64");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prepareForStdio()
|
public void prepareForStdio()
|
||||||
{
|
{
|
||||||
scanner.addIncludePath(
|
scanner.addIncludePath(
|
||||||
"C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\include");
|
"C:\\Program Files\\Microsoft Visual Studio\\VC98\\Include");
|
||||||
scanner.addDefinition("_MSC_VER", "1100");
|
scanner.addDefinition("_MSC_VER", "1100");
|
||||||
scanner.addDefinition("__STDC__", "1");
|
scanner.addDefinition("__STDC__", "1");
|
||||||
scanner.addDefinition("_INTEGRAL_MAX_BITS", "64");
|
scanner.addDefinition("_INTEGRAL_MAX_BITS", "64");
|
||||||
scanner.addDefinition("_WIN32", "");
|
scanner.addDefinition("_WIN32", "");
|
||||||
|
scanner.addDefinition( "_M_IX86", "300");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testConcatenation()
|
public void testConcatenation()
|
||||||
{
|
{
|
||||||
if (doConcatenation)
|
try
|
||||||
{
|
{
|
||||||
try
|
initializeScanner("#define F1 3\n#define F2 F1##F1\nint x=F2;");
|
||||||
{
|
validateToken(Token.t_int);
|
||||||
initializeScanner("#define F1 3\n#define F2 F1##F1\nint x=F2;");
|
validateDefinition("F1", "3");
|
||||||
validateToken(Token.t_int);
|
validateDefinition( "F2", "F1##F1");
|
||||||
validateDefinition("F1", "3");
|
validateIdentifier("x");
|
||||||
validateDefinition("F2", "F1##F1");
|
validateToken(Token.tASSIGN);
|
||||||
validateIdentifier("x");
|
validateInteger("33");
|
||||||
validateToken(Token.tASSIGN);
|
validateToken(Token.tSEMI);
|
||||||
validateInteger("33");
|
validateEOF();
|
||||||
validateToken(Token.tSEMI);
|
|
||||||
validateEOF();
|
initializeScanner("#define PREFIX RT_\n#define RUN PREFIX##Run");
|
||||||
|
validateEOF();
|
||||||
initializeScanner("#define PREFIX RT_\n#define RUN PREFIX##Run");
|
validateDefinition( "PREFIX", "RT_" );
|
||||||
validateEOF();
|
validateDefinition( "RUN", "PREFIX##Run" );
|
||||||
validateDefinition( "PREFIX", "RT_" );
|
}
|
||||||
validateDefinition( "RUN", "RT_Run" );
|
catch (Exception e)
|
||||||
}
|
{
|
||||||
catch (Exception e)
|
fail(EXCEPTION_THROWN + e.toString());
|
||||||
{
|
}
|
||||||
fail(EXCEPTION_THROWN + e.toString());
|
|
||||||
}
|
try
|
||||||
|
{
|
||||||
|
initializeScanner( "#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name\n DECLARE_HANDLE( joe )" );
|
||||||
|
validateToken( Token.t_struct );
|
||||||
|
validateIdentifier( "joe__");
|
||||||
|
validateToken( Token.tLBRACE);
|
||||||
|
validateToken( Token.t_int );
|
||||||
|
validateIdentifier( "unused");
|
||||||
|
validateToken( Token.tSEMI );
|
||||||
|
validateToken( Token.tRBRACE );
|
||||||
|
validateToken( Token.tSEMI );
|
||||||
|
validateToken( Token.t_typedef );
|
||||||
|
validateToken( Token.t_struct );
|
||||||
|
validateIdentifier( "joe__" );
|
||||||
|
validateToken( Token.tSTAR );
|
||||||
|
validateIdentifier( "joe");
|
||||||
|
validateEOF();
|
||||||
|
}
|
||||||
|
catch( Exception e )
|
||||||
|
{
|
||||||
|
fail(EXCEPTION_THROWN + e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1089,5 +1111,5 @@ public class ScannerTestCase extends TestCase
|
||||||
{
|
{
|
||||||
fail(EXCEPTION_THROWN + se.toString());
|
fail(EXCEPTION_THROWN + se.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue