diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog-parser b/core/org.eclipse.cdt.core/parser/ChangeLog-parser index 570274fb21c..26d4f6fde7a 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog-parser +++ b/core/org.eclipse.cdt.core/parser/ChangeLog-parser @@ -1,3 +1,6 @@ +2004-03-11 John Camelon + Refactoring of Scanner to allow reuse in GCCScannerExtension + 2004-03-10 John Camelon Further performance improvements in Scanner. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/GCCScannerExtension.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/GCCScannerExtension.java index 844b4197f5b..a34dfafe441 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/GCCScannerExtension.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/GCCScannerExtension.java @@ -10,6 +10,9 @@ ***********************************************************************/ 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.ParserLanguage; 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) * @see org.eclipse.cdt.core.parser.extension.IScannerExtension#canHandlePreprocessorDirective(java.lang.String) */ public boolean canHandlePreprocessorDirective(String directive) { - if( directive.equals("#include_next")) return true; //$NON-NLS-1$ - return false; + return directives.contains( directive ); } /* (non-Javadoc) @@ -70,7 +80,17 @@ public class GCCScannerExtension implements IScannerExtension { public void handlePreprocessorDirective(String directive, String restOfLine) { 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 + 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 } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Scanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Scanner.java index 40c389fe23f..7fc8ccf744d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Scanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Scanner.java @@ -104,7 +104,7 @@ public class Scanner implements IScanner { 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); 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(); } - 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 { CodeReader duple = null; @@ -597,7 +547,7 @@ public class Scanner implements IScanner { while (iter.hasNext()) { String path = (String)iter.next(); - duple = createReaderDuple( path, fileName ); + duple = ScannerUtility.createReaderDuple( path, fileName, scannerData.getClientRequestor() ); if( duple != null ) break totalLoop; } @@ -608,7 +558,7 @@ public class Scanner implements IScanner { } 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 ) break totalLoop; useIncludePaths = true; @@ -763,8 +713,6 @@ public class Scanner implements IScanner { tokenizingMacroReplacementList = mr; } - private static final IScannerInfo EMPTY_INFO = new ScannerInfo(); - public int getCharacter() throws ScannerException { if( ! initialContextInitialized ) @@ -773,7 +721,7 @@ public class Scanner implements IScanner { return getChar(); } - private int getChar() throws ScannerException + int getChar() throws ScannerException { return getChar( false ); } @@ -928,7 +876,7 @@ public class Scanner implements IScanner { return c; } - private void ungetChar(int c) throws ScannerException{ + void ungetChar(int c) throws ScannerException{ scannerData.getContextStack().getCurrentContext().pushUndo(c); try { @@ -2455,81 +2403,18 @@ public class Scanner implements IScanner { int nameLine = scannerData.getContextStack().getCurrentLineNumber(); String includeLine = getRestOfPreprocessorLine(); int endLine = scannerData.getContextStack().getCurrentLineNumber(); - StringBuffer fileName = new StringBuffer(); - boolean useIncludePath = true; - int startOffset = baseOffset; - int 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; - - 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 + potentialErrorLine.append( includeLine ); + + ScannerUtility.InclusionDirective directive = null; + try + { + directive = ScannerUtility.parseInclusionDirective( scannerData, scannerExtension, includeLine, baseOffset ); + } + catch( ScannerUtility.InclusionParseException ipe ) + { handleProblem( IProblem.PREPROCESSOR_INVALID_DIRECTIVE, potentialErrorLine.toString(), beginningOffset, false, true ); - - String f = fileName.toString(); + return; + } if( scannerData.getParserMode() == ParserMode.QUICK_PARSE ) { @@ -2540,13 +2425,13 @@ public class Scanner implements IScanner { { i = scannerData.getASTFactory().createInclusion( - f, + directive.getFilename(), "", //$NON-NLS-1$ - !useIncludePath, + !directive.useIncludePaths(), beginningOffset, startLine, - startOffset, - startOffset + f.length(), nameLine, endOffset, endLine); + directive.getStartOffset(), + directive.getStartOffset() + directive.getFilename().length(), nameLine, directive.getEndOffset(), endLine); } catch (Exception e) { @@ -2560,7 +2445,7 @@ public class Scanner implements IScanner { } } 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(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerUtility.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerUtility.java new file mode 100644 index 00000000000..b7109e3fbd7 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerUtility.java @@ -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 ; + } + + } +}