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

Refactoring of Scanner to allow reuse in GCCScannerExtension for #include_next

This commit is contained in:
John Camelon 2004-03-11 20:47:34 +00:00
parent da87b50b7f
commit 2a28b0cfa7
4 changed files with 250 additions and 138 deletions

View file

@ -1,3 +1,6 @@
2004-03-11 John Camelon
Refactoring of Scanner to allow reuse in GCCScannerExtension
2004-03-10 John Camelon 2004-03-10 John Camelon
Further performance improvements in Scanner. Further performance improvements in Scanner.

View file

@ -10,6 +10,9 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.cdt.core.parser.IScanner; import org.eclipse.cdt.core.parser.IScanner;
import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.extension.IScannerExtension; import org.eclipse.cdt.core.parser.extension.IScannerExtension;
@ -56,12 +59,19 @@ public class GCCScannerExtension implements IScannerExtension {
} }
} }
private static final Set directives;
static
{
directives = new HashSet();
directives.add( "#include_next" ); //$NON-NLS-1$
directives.add( "#warning"); //$NON-NLS-1$
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.core.parser.extension.IScannerExtension#canHandlePreprocessorDirective(java.lang.String) * @see org.eclipse.cdt.core.parser.extension.IScannerExtension#canHandlePreprocessorDirective(java.lang.String)
*/ */
public boolean canHandlePreprocessorDirective(String directive) { public boolean canHandlePreprocessorDirective(String directive) {
if( directive.equals("#include_next")) return true; //$NON-NLS-1$ return directives.contains( directive );
return false;
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -70,7 +80,17 @@ public class GCCScannerExtension implements IScannerExtension {
public void handlePreprocessorDirective(String directive, String restOfLine) { public void handlePreprocessorDirective(String directive, String restOfLine) {
if( directive.equals("#include_next") ) //$NON-NLS-1$ if( directive.equals("#include_next") ) //$NON-NLS-1$
{ {
scannerData.getLogService().traceLog( "GCCScannerExtension handling #include_next directive" ); //$NON-NLS-1$
// figure out the name of the current file and its path // figure out the name of the current file and its path
IScannerContext context = scannerData.getContextStack().getCurrentContext();
if( context.getKind() != IScannerContext.ContextKind.INCLUSION )
{
//handle appropriate error
}
// String fullInclusionPath = context.getFilename();
// IASTInclusion inclusion = context.getExtension();
// search through include paths // search through include paths
} }
} }

View file

@ -104,7 +104,7 @@ public class Scanner implements IScanner {
throw new ScannerException( problem ); throw new ScannerException( problem );
} }
private Scanner( Reader reader, String filename, Map definitions, List includePaths, ISourceElementRequestor requestor, ParserMode mode, ParserLanguage language, IParserLogService log, IScannerExtension extension ) Scanner( Reader reader, String filename, Map definitions, List includePaths, ISourceElementRequestor requestor, ParserMode mode, ParserLanguage language, IParserLogService log, IScannerExtension extension )
{ {
String [] incs = (String [])includePaths.toArray(STRING_ARRAY); String [] incs = (String [])includePaths.toArray(STRING_ARRAY);
scannerData = new ScannerData( this, log, requestor, mode, filename, reader, language, new ScannerInfo( definitions, incs ), new ContextStack( this, log ) ); scannerData = new ScannerData( this, log, requestor, mode, filename, reader, language, new ScannerInfo( definitions, incs ), new ContextStack( this, log ) );
@ -534,56 +534,6 @@ public class Scanner implements IScanner {
return buffer.toString(); return buffer.toString();
} }
protected CodeReader createReaderDuple( String path, String fileName )
{
File pathFile = new File(path);
//TODO assert pathFile.isDirectory();
StringBuffer newPathBuffer = new StringBuffer( pathFile.getPath() );
newPathBuffer.append( File.separatorChar );
newPathBuffer.append( fileName );
//remove ".." and "." segments
String finalPath = reconcilePath( newPathBuffer.toString() );
Reader r = scannerData.getClientRequestor().createReader( finalPath );
if( r != null )
return new CodeReader( finalPath, r );
return null;
}
/**
* @param string
* @return
*/
private String reconcilePath(String originalPath ) {
if( originalPath == null ) return null;
String [] segments = originalPath.split( "[/\\\\]" ); //$NON-NLS-1$
if( segments.length == 1 ) return originalPath;
Vector results = new Vector();
for( int i = 0; i < segments.length; ++i )
{
String segment = segments[i];
if( segment.equals( ".") ) continue; //$NON-NLS-1$
if( segment.equals("..") ) //$NON-NLS-1$
{
if( results.size() > 0 )
results.removeElementAt( results.size() - 1 );
}
else
results.add( segment );
}
StringBuffer buffer = new StringBuffer();
Iterator i = results.iterator();
while( i.hasNext() )
{
buffer.append( (String)i.next() );
if( i.hasNext() )
buffer.append( File.separatorChar );
}
scannerData.getLogService().traceLog( "Path has been reduced to " + buffer.toString()); //$NON-NLS-1$
return buffer.toString();
}
protected void handleInclusion(String fileName, boolean useIncludePaths, int beginOffset, int startLine, int nameOffset, int nameLine, int endOffset, int endLine ) throws ScannerException { protected void handleInclusion(String fileName, boolean useIncludePaths, int beginOffset, int startLine, int nameOffset, int nameLine, int endOffset, int endLine ) throws ScannerException {
CodeReader duple = null; CodeReader duple = null;
@ -597,7 +547,7 @@ public class Scanner implements IScanner {
while (iter.hasNext()) { while (iter.hasNext()) {
String path = (String)iter.next(); String path = (String)iter.next();
duple = createReaderDuple( path, fileName ); duple = ScannerUtility.createReaderDuple( path, fileName, scannerData.getClientRequestor() );
if( duple != null ) if( duple != null )
break totalLoop; break totalLoop;
} }
@ -608,7 +558,7 @@ public class Scanner implements IScanner {
} }
else // local inclusion else // local inclusion
{ {
duple = createReaderDuple( new File( scannerData.getContextStack().getCurrentContext().getFilename() ).getParentFile().getAbsolutePath(), fileName ); duple = ScannerUtility.createReaderDuple( new File( scannerData.getContextStack().getCurrentContext().getFilename() ).getParentFile().getAbsolutePath(), fileName, scannerData.getClientRequestor() );
if( duple != null ) if( duple != null )
break totalLoop; break totalLoop;
useIncludePaths = true; useIncludePaths = true;
@ -763,8 +713,6 @@ public class Scanner implements IScanner {
tokenizingMacroReplacementList = mr; tokenizingMacroReplacementList = mr;
} }
private static final IScannerInfo EMPTY_INFO = new ScannerInfo();
public int getCharacter() throws ScannerException public int getCharacter() throws ScannerException
{ {
if( ! initialContextInitialized ) if( ! initialContextInitialized )
@ -773,7 +721,7 @@ public class Scanner implements IScanner {
return getChar(); return getChar();
} }
private int getChar() throws ScannerException int getChar() throws ScannerException
{ {
return getChar( false ); return getChar( false );
} }
@ -928,7 +876,7 @@ public class Scanner implements IScanner {
return c; return c;
} }
private void ungetChar(int c) throws ScannerException{ void ungetChar(int c) throws ScannerException{
scannerData.getContextStack().getCurrentContext().pushUndo(c); scannerData.getContextStack().getCurrentContext().pushUndo(c);
try try
{ {
@ -2455,81 +2403,18 @@ public class Scanner implements IScanner {
int nameLine = scannerData.getContextStack().getCurrentLineNumber(); int nameLine = scannerData.getContextStack().getCurrentLineNumber();
String includeLine = getRestOfPreprocessorLine(); String includeLine = getRestOfPreprocessorLine();
int endLine = scannerData.getContextStack().getCurrentLineNumber(); int endLine = scannerData.getContextStack().getCurrentLineNumber();
StringBuffer fileName = new StringBuffer(); potentialErrorLine.append( includeLine );
boolean useIncludePath = true;
int startOffset = baseOffset;
int endOffset = baseOffset;
if (! includeLine.equals("")) { //$NON-NLS-1$ ScannerUtility.InclusionDirective directive = null;
Scanner helperScanner = new Scanner( try
new StringReader(includeLine), {
null, directive = ScannerUtility.parseInclusionDirective( scannerData, scannerExtension, includeLine, baseOffset );
scannerData.getDefinitions(), scannerData.getIncludePathNames(), }
NULL_REQUESTOR, catch( ScannerUtility.InclusionParseException ipe )
scannerData.getParserMode(), {
scannerData.getLanguage(), NULL_LOG_SERVICE, (IScannerExtension)(scannerExtension.clone()) );
helperScanner.setForInclusion( true );
IToken t = null;
potentialErrorLine.append( includeLine );
try {
t = helperScanner.nextToken(false);
} catch (EndOfFileException eof) {
handleProblem( IProblem.PREPROCESSOR_INVALID_DIRECTIVE, potentialErrorLine.toString(), beginningOffset, false, true );
return;
}
try {
if (t.getType() == IToken.tSTRING) {
fileName.append(t.getImage());
startOffset = baseOffset + t.getOffset();
endOffset = baseOffset + t.getEndOffset();
useIncludePath = false;
// This should throw EOF
t = helperScanner.nextToken(false);
handleProblem( IProblem.PREPROCESSOR_INVALID_DIRECTIVE, potentialErrorLine.toString(), beginningOffset, false, true );
return;
} else if (t.getType() == IToken.tLT) {
try {
t = helperScanner.nextToken(false);
startOffset = baseOffset + t.getOffset();
while (t.getType() != IToken.tGT) {
fileName.append(t.getImage());
helperScanner.skipOverWhitespace();
int c = helperScanner.getChar();
if (c == '\\') fileName.append('\\'); else helperScanner.ungetChar(c);
t = helperScanner.nextToken(false);
}
endOffset = baseOffset + t.getEndOffset();
} catch (EndOfFileException eof) {
handleProblem( IProblem.PREPROCESSOR_INVALID_DIRECTIVE, potentialErrorLine.toString(), beginningOffset, false, true );
return;
}
// This should throw EOF
t = helperScanner.nextToken(false);
handleProblem( IProblem.PREPROCESSOR_INVALID_DIRECTIVE, potentialErrorLine.toString(), beginningOffset, false, true );
return;
} else
handleProblem( IProblem.PREPROCESSOR_INVALID_DIRECTIVE, potentialErrorLine.toString(), beginningOffset, false, true );
}
catch( EndOfFileException eof )
{
// good
}
} else
handleProblem( IProblem.PREPROCESSOR_INVALID_DIRECTIVE, potentialErrorLine.toString(), beginningOffset, false, true ); handleProblem( IProblem.PREPROCESSOR_INVALID_DIRECTIVE, potentialErrorLine.toString(), beginningOffset, false, true );
return;
String f = fileName.toString(); }
if( scannerData.getParserMode() == ParserMode.QUICK_PARSE ) if( scannerData.getParserMode() == ParserMode.QUICK_PARSE )
{ {
@ -2540,13 +2425,13 @@ public class Scanner implements IScanner {
{ {
i = i =
scannerData.getASTFactory().createInclusion( scannerData.getASTFactory().createInclusion(
f, directive.getFilename(),
"", //$NON-NLS-1$ "", //$NON-NLS-1$
!useIncludePath, !directive.useIncludePaths(),
beginningOffset, beginningOffset,
startLine, startLine,
startOffset, directive.getStartOffset(),
startOffset + f.length(), nameLine, endOffset, endLine); directive.getStartOffset() + directive.getFilename().length(), nameLine, directive.getEndOffset(), endLine);
} }
catch (Exception e) catch (Exception e)
{ {
@ -2560,7 +2445,7 @@ public class Scanner implements IScanner {
} }
} }
else else
handleInclusion(f.trim(), useIncludePath, beginningOffset, startLine, startOffset, nameLine, endOffset, endLine); handleInclusion(directive.getFilename().trim(), directive.useIncludePaths(), beginningOffset, startLine, directive.getStartOffset(), nameLine, directive.getEndOffset(), endLine);
} }
protected static final Hashtable EMPTY_MAP = new Hashtable(); protected static final Hashtable EMPTY_MAP = new Hashtable();

View file

@ -0,0 +1,204 @@
/*******************************************************************************
* Copyright (c) 2003, 2004 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.scanner;
import java.io.File;
import java.io.Reader;
import java.io.StringReader;
import java.util.Iterator;
import java.util.Vector;
import org.eclipse.cdt.core.parser.CodeReader;
import org.eclipse.cdt.core.parser.EndOfFileException;
import org.eclipse.cdt.core.parser.IParserLogService;
import org.eclipse.cdt.core.parser.ISourceElementRequestor;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.NullLogService;
import org.eclipse.cdt.core.parser.NullSourceElementRequestor;
import org.eclipse.cdt.core.parser.ScannerException;
import org.eclipse.cdt.core.parser.extension.IScannerExtension;
/**
* @author jcamelon
*/
public class ScannerUtility {
/**
* @param string
* @return
*/
static String reconcilePath(String originalPath ) {
if( originalPath == null ) return null;
String [] segments = originalPath.split( "[/\\\\]" ); //$NON-NLS-1$
if( segments.length == 1 ) return originalPath;
Vector results = new Vector();
for( int i = 0; i < segments.length; ++i )
{
String segment = segments[i];
if( segment.equals( ".") ) continue; //$NON-NLS-1$
if( segment.equals("..") ) //$NON-NLS-1$
{
if( results.size() > 0 )
results.removeElementAt( results.size() - 1 );
}
else
results.add( segment );
}
StringBuffer buffer = new StringBuffer();
Iterator i = results.iterator();
while( i.hasNext() )
{
buffer.append( (String)i.next() );
if( i.hasNext() )
buffer.append( File.separatorChar );
}
return buffer.toString();
}
static CodeReader createReaderDuple( String path, String fileName, ISourceElementRequestor requestor )
{
File pathFile = new File(path);
//TODO assert pathFile.isDirectory();
StringBuffer newPathBuffer = new StringBuffer( pathFile.getPath() );
newPathBuffer.append( File.separatorChar );
newPathBuffer.append( fileName );
//remove ".." and "." segments
String finalPath = reconcilePath( newPathBuffer.toString() );
Reader r = requestor.createReader( finalPath );
if( r != null )
return new CodeReader( finalPath, r );
return null;
}
static class InclusionDirective
{
public InclusionDirective( String fileName, boolean useIncludePaths, int startOffset, int endOffset )
{
this.fileName = fileName;
this.useIncludePaths = useIncludePaths;
this.startOffset = startOffset;
this.endOffset = endOffset;
}
private final boolean useIncludePaths;
private final String fileName;
private final int startOffset;
private final int endOffset;
boolean useIncludePaths()
{
return useIncludePaths;
}
String getFilename()
{
return fileName;
}
int getStartOffset()
{
return startOffset;
}
int getEndOffset()
{
return endOffset;
}
}
static class InclusionParseException extends Exception
{
}
private static final ISourceElementRequestor NULL_REQUESTOR = new NullSourceElementRequestor();
private static final IParserLogService NULL_LOG_SERVICE = new NullLogService();
private static final InclusionParseException INCLUSION_PARSE_EXCEPTION = new InclusionParseException();
static InclusionDirective parseInclusionDirective( IScannerData scannerData, IScannerExtension scannerExtension, String includeLine, int baseOffset ) throws InclusionParseException
{
try
{
boolean useIncludePath = true;
StringBuffer fileNameBuffer = new StringBuffer();
int startOffset = baseOffset, endOffset = baseOffset;
if (! includeLine.equals("")) { //$NON-NLS-1$
Scanner helperScanner = new Scanner(
new StringReader(includeLine),
null,
scannerData.getDefinitions(), scannerData.getIncludePathNames(),
NULL_REQUESTOR,
scannerData.getParserMode(),
scannerData.getLanguage(), NULL_LOG_SERVICE, (IScannerExtension)(scannerExtension.clone()) );
helperScanner.setForInclusion( true );
IToken t = null;
try {
t = helperScanner.nextToken(false);
} catch (EndOfFileException eof) {
throw INCLUSION_PARSE_EXCEPTION ;
}
try {
if (t.getType() == IToken.tSTRING) {
fileNameBuffer.append(t.getImage());
startOffset = baseOffset + t.getOffset();
endOffset = baseOffset + t.getEndOffset();
useIncludePath = false;
// This should throw EOF
t = helperScanner.nextToken(false);
throw INCLUSION_PARSE_EXCEPTION ;
} else if (t.getType() == IToken.tLT) {
try {
t = helperScanner.nextToken(false);
startOffset = baseOffset + t.getOffset();
while (t.getType() != IToken.tGT) {
fileNameBuffer.append(t.getImage());
helperScanner.skipOverWhitespace();
int c = helperScanner.getChar();
if (c == '\\') fileNameBuffer.append('\\'); else helperScanner.ungetChar(c);
t = helperScanner.nextToken(false);
}
endOffset = baseOffset + t.getEndOffset();
} catch (EndOfFileException eof) {
throw INCLUSION_PARSE_EXCEPTION ;
}
// This should throw EOF
t = helperScanner.nextToken(false);
throw INCLUSION_PARSE_EXCEPTION ;
} else
throw INCLUSION_PARSE_EXCEPTION ;
}
catch( EndOfFileException eof )
{
// good
}
} else
throw INCLUSION_PARSE_EXCEPTION ;
return new InclusionDirective( fileNameBuffer.toString(), useIncludePath, startOffset, endOffset );
}
catch( ScannerException se )
{
throw INCLUSION_PARSE_EXCEPTION ;
}
}
}