diff options
Diffstat (limited to 'core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java')
-rw-r--r-- | core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java | 2785 |
1 files changed, 1440 insertions, 1345 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java index 51cbbf4e3d4..4b82a263411 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java @@ -85,44 +85,44 @@ import org.osgi.framework.Version; public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { public static final String PROP_VALUE = "CPreprocessor"; //$NON-NLS-1$ - public static final int tDEFINED= IToken.FIRST_RESERVED_PREPROCESSOR; - public static final int tEXPANDED_IDENTIFIER= IToken.FIRST_RESERVED_PREPROCESSOR + 1; - public static final int tSCOPE_MARKER= IToken.FIRST_RESERVED_PREPROCESSOR + 2; - public static final int tSPACE= IToken.FIRST_RESERVED_PREPROCESSOR + 3; - public static final int tNOSPACE= IToken.FIRST_RESERVED_PREPROCESSOR + 4; - public static final int tMACRO_PARAMETER= IToken.FIRST_RESERVED_PREPROCESSOR + 5; + public static final int tDEFINED = IToken.FIRST_RESERVED_PREPROCESSOR; + public static final int tEXPANDED_IDENTIFIER = IToken.FIRST_RESERVED_PREPROCESSOR + 1; + public static final int tSCOPE_MARKER = IToken.FIRST_RESERVED_PREPROCESSOR + 2; + public static final int tSPACE = IToken.FIRST_RESERVED_PREPROCESSOR + 3; + public static final int tNOSPACE = IToken.FIRST_RESERVED_PREPROCESSOR + 4; + public static final int tMACRO_PARAMETER = IToken.FIRST_RESERVED_PREPROCESSOR + 5; public static final int t__HAS_FEATURE = IToken.FIRST_RESERVED_PREPROCESSOR + 6; private static final int ORIGIN_PREPROCESSOR_DIRECTIVE = OffsetLimitReachedException.ORIGIN_PREPROCESSOR_DIRECTIVE; private static final int ORIGIN_INACTIVE_CODE = OffsetLimitReachedException.ORIGIN_INACTIVE_CODE; - - private static final char[] ONE = "1".toCharArray(); //$NON-NLS-1$ - - // Standard built-ins - private static final ObjectStyleMacro __CDT_PARSER__= new ObjectStyleMacro("__CDT_PARSER__".toCharArray(), //$NON-NLS-1$ - Integer.toString(getCDTVersion()).toCharArray()); - private static final ObjectStyleMacro __cplusplus = - new ObjectStyleMacro("__cplusplus".toCharArray(), "201103L".toCharArray()); //$NON-NLS-1$ //$NON-NLS-2$ - private static final ObjectStyleMacro __STDC__ = new ObjectStyleMacro("__STDC__".toCharArray(), ONE); //$NON-NLS-1$ - private static final ObjectStyleMacro __STDC_HOSTED__ = new ObjectStyleMacro("__STDC_HOSTED__".toCharArray(), ONE); //$NON-NLS-1$ - private static final ObjectStyleMacro __STDC_VERSION__ = - new ObjectStyleMacro("__STDC_VERSION__".toCharArray(), "199901L".toCharArray()); //$NON-NLS-1$ //$NON-NLS-2$ - - private static final DynamicMacro __FILE__= new FileMacro("__FILE__".toCharArray()); //$NON-NLS-1$ - private static final DynamicMacro __DATE__= new DateMacro("__DATE__".toCharArray()); //$NON-NLS-1$ - private static final DynamicMacro __TIME__ = new TimeMacro("__TIME__".toCharArray()); //$NON-NLS-1$ - private static final DynamicMacro __LINE__ = new LineMacro("__LINE__".toCharArray()); //$NON-NLS-1$ - private static final char[] __COUNTER__ = "__COUNTER__".toCharArray(); //$NON-NLS-1$ + + private static final char[] ONE = "1".toCharArray(); //$NON-NLS-1$ + + // Standard built-ins + private static final ObjectStyleMacro __CDT_PARSER__ = new ObjectStyleMacro("__CDT_PARSER__".toCharArray(), //$NON-NLS-1$ + Integer.toString(getCDTVersion()).toCharArray()); + private static final ObjectStyleMacro __cplusplus = new ObjectStyleMacro("__cplusplus".toCharArray(), //$NON-NLS-1$ + "201103L".toCharArray()); //$NON-NLS-1$ + private static final ObjectStyleMacro __STDC__ = new ObjectStyleMacro("__STDC__".toCharArray(), ONE); //$NON-NLS-1$ + private static final ObjectStyleMacro __STDC_HOSTED__ = new ObjectStyleMacro("__STDC_HOSTED__".toCharArray(), ONE); //$NON-NLS-1$ + private static final ObjectStyleMacro __STDC_VERSION__ = new ObjectStyleMacro("__STDC_VERSION__".toCharArray(), //$NON-NLS-1$ + "199901L".toCharArray()); //$NON-NLS-1$ + + private static final DynamicMacro __FILE__ = new FileMacro("__FILE__".toCharArray()); //$NON-NLS-1$ + private static final DynamicMacro __DATE__ = new DateMacro("__DATE__".toCharArray()); //$NON-NLS-1$ + private static final DynamicMacro __TIME__ = new TimeMacro("__TIME__".toCharArray()); //$NON-NLS-1$ + private static final DynamicMacro __LINE__ = new LineMacro("__LINE__".toCharArray()); //$NON-NLS-1$ + private static final char[] __COUNTER__ = "__COUNTER__".toCharArray(); //$NON-NLS-1$ private static final char[] ONCE = "once".toCharArray(); //$NON-NLS-1$ - static final int NO_EXPANSION = 0x01; + static final int NO_EXPANSION = 0x01; // Set in contexts where preprocessor intrinsics such as 'defined' // or '__has_feature' need to be recognized. - static final int PROTECT_INTRINSICS = 0x02; - static final int STOP_AT_NL = 0x04; - static final int CHECK_NUMBERS = 0x08; - static final int REPORT_SIGNIFICANT_MACROS = 0x10; - static final int IGNORE_UNDEFINED_SIGNIFICANT_MACROS = 0x20; + static final int PROTECT_INTRINSICS = 0x02; + static final int STOP_AT_NL = 0x04; + static final int CHECK_NUMBERS = 0x08; + static final int REPORT_SIGNIFICANT_MACROS = 0x10; + static final int IGNORE_UNDEFINED_SIGNIFICANT_MACROS = 0x20; private static final int MAX_INCLUSION_DEPTH = 200; @@ -132,7 +132,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { * Returns an integer, suitable for use as a macro value, representing the current * version of the CDT feature, composited into a single number. * For example, version 9.2.1 would be composited into 90201. - * Used as the value of the __CDT_PARSER__ macro. + * Used as the value of the __CDT_PARSER__ macro. */ public static int getCDTVersion() { Version version = CCorePlugin.getCDTFeatureVersion(); @@ -146,13 +146,13 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { // Fall back to the old approach of defining __CDT_PARSER__ as 1. return 1; } - + private final class MacroDictionary implements IMacroDictionary, ISignificantMacros.IVisitor { @Override public boolean satisfies(ISignificantMacros significantMacros) { return significantMacros.accept(this); } - + @Override public boolean visitDefined(char[] macro) { return isDefined(macro); @@ -175,66 +175,66 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } private interface IIncludeFileTester<T> { - T checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath); - } + T checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath); + } - final private IIncludeFileTester<InternalFileContent> createCodeReaderTester= new IIncludeFileTester<InternalFileContent>() { - @Override + final private IIncludeFileTester<InternalFileContent> createCodeReaderTester = new IIncludeFileTester<InternalFileContent>() { + @Override public InternalFileContent checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) { final InternalFileContent fc; - IFileNomination once= fFileContentProvider.isIncludedWithPragmaOnceSemantics(path); + IFileNomination once = fFileContentProvider.isIncludedWithPragmaOnceSemantics(path); if (once != null) { - fc= new InternalFileContent(path, InclusionKind.SKIP_FILE); + fc = new InternalFileContent(path, InclusionKind.SKIP_FILE); } else { - fc= fFileContentProvider.getContentForInclusion(path, fMacroDictionaryFacade); + fc = fFileContentProvider.getContentForInclusion(path, fMacroDictionaryFacade); } if (fc != null) { fc.setFoundByHeuristics(isHeuristicMatch); fc.setFoundOnPath(onPath); } return fc; - } - }; + } + }; - private static class IncludeResolution { - final String fLocation; - final boolean fHeuristic; + private static class IncludeResolution { + final String fLocation; + final boolean fHeuristic; - IncludeResolution(String location, boolean heusistic) { - fLocation = location; - fHeuristic = heusistic; - } - } + IncludeResolution(String location, boolean heusistic) { + fLocation = location; + fHeuristic = heusistic; + } + } - final private IIncludeFileTester<IncludeResolution> createPathTester= new IIncludeFileTester<IncludeResolution>() { - @Override + final private IIncludeFileTester<IncludeResolution> createPathTester = new IIncludeFileTester<IncludeResolution>() { + @Override public IncludeResolution checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) { - if (fFileContentProvider.getInclusionExists(path)) { - return new IncludeResolution(path, isHeuristicMatch); - } - return null; - } - }; + if (fFileContentProvider.getInclusionExists(path)) { + return new IncludeResolution(path, isHeuristicMatch); + } + return null; + } + }; private final class TokenSequence implements ITokenSequence { private final boolean fStopAtNewline; TokenSequence(boolean stopAtNewline) { - fStopAtNewline= stopAtNewline; + fStopAtNewline = stopAtNewline; } @Override public Token nextToken() throws OffsetLimitReachedException { - final Lexer lexer= fCurrentContext.getLexer(); - Token t= lexer.nextToken(); - if (t.getType() == IToken.tPOUND && lexer.currentTokenIsFirstOnLine()) { - executeDirective(lexer, t.getOffset(), true); - t= lexer.currentToken(); - } - if (fStopAtNewline && t.getType() == Lexer.tNEWLINE) - return new Token(IToken.tEND_OF_INPUT, null, 0, 0); - - return t; + final Lexer lexer = fCurrentContext.getLexer(); + Token t = lexer.nextToken(); + if (t.getType() == IToken.tPOUND && lexer.currentTokenIsFirstOnLine()) { + executeDirective(lexer, t.getOffset(), true); + t = lexer.currentToken(); + } + if (fStopAtNewline && t.getType() == Lexer.tNEWLINE) + return new Token(IToken.tEND_OF_INPUT, null, 0, 0); + + return t; } @Override @@ -244,54 +244,54 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { @Override public Token currentToken() { - Token t= fCurrentContext.currentLexerToken(); - if (fStopAtNewline && t.getType() == Lexer.tNEWLINE) - return new Token(IToken.tEND_OF_INPUT, null, 0, 0); - - return t; + Token t = fCurrentContext.currentLexerToken(); + if (fStopAtNewline && t.getType() == Lexer.tNEWLINE) + return new Token(IToken.tEND_OF_INPUT, null, 0, 0); + + return t; } } private Set<String> sSupportedFeatures; - - TokenSequence fInputToMacroExpansion= new TokenSequence(false); - TokenSequence fLineInputToMacroExpansion= new TokenSequence(true); - final private AbstractParserLogService fLog; - final private InternalFileContentProvider fFileContentProvider; + TokenSequence fInputToMacroExpansion = new TokenSequence(false); + TokenSequence fLineInputToMacroExpansion = new TokenSequence(true); + + final private AbstractParserLogService fLog; + final private InternalFileContentProvider fFileContentProvider; - private final IIncludeFileResolutionHeuristics fIncludeFileResolutionHeuristics; - private final ExpressionEvaluator fExpressionEvaluator; + private final IIncludeFileResolutionHeuristics fIncludeFileResolutionHeuristics; + private final ExpressionEvaluator fExpressionEvaluator; private final MacroDefinitionParser fMacroDefinitionParser; private final MacroExpander fMacroExpander; - // configuration - final private LexerOptions fLexOptions= new LexerOptions(); - final private char[] fAdditionalNumericLiteralSuffixes; - final private CharArrayIntMap fKeywords; - final private CharArrayIntMap fPPKeywords; - private final IncludeSearchPath fIncludeSearchPath; - private String[][] fPreIncludedFiles= null; + // configuration + final private LexerOptions fLexOptions = new LexerOptions(); + final private char[] fAdditionalNumericLiteralSuffixes; + final private CharArrayIntMap fKeywords; + final private CharArrayIntMap fPPKeywords; + private final IncludeSearchPath fIncludeSearchPath; + private String[][] fPreIncludedFiles = null; - private int fContentAssistLimit= -1; - private boolean fHandledCompletion= false; - private boolean fSplitShiftRightOperator= false; + private int fContentAssistLimit = -1; + private boolean fHandledCompletion = false; + private boolean fSplitShiftRightOperator = false; - // State information - private final CharArrayMap<PreprocessorMacro> fMacroDictionary = new CharArrayMap<>(512); + // State information + private final CharArrayMap<PreprocessorMacro> fMacroDictionary = new CharArrayMap<>(512); private final IMacroDictionary fMacroDictionaryFacade = new MacroDictionary(); - private final LocationMap fLocationMap; + private final LocationMap fLocationMap; private CharArraySet fPreventInclusion; private CharArraySet fImports; private final ScannerContext fRootContext; protected ScannerContext fCurrentContext; - private boolean isCancelled; - private boolean fIsFirstFetchToken= true; + private boolean isCancelled; + private boolean fIsFirstFetchToken = true; private Token fPrefetchedTokens; - private Token fLastToken; + private Token fLastToken; private InternalFileContent fRootContent; private boolean fHandledEndOfTranslationUnit; @@ -300,67 +300,66 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { private char[] fExternIncludeGuard; private Set<String> fTracedGuards; - public CPreprocessor(FileContent fileContent, IScannerInfo info, ParserLanguage language, - IParserLogService log, IScannerExtensionConfiguration configuration, - IncludeFileContentProvider readerFactory) { + public CPreprocessor(FileContent fileContent, IScannerInfo info, ParserLanguage language, IParserLogService log, + IScannerExtensionConfiguration configuration, IncludeFileContentProvider readerFactory) { Token.resetCounterFor(info); - if (readerFactory instanceof InternalFileContentProvider) { - fFileContentProvider= (InternalFileContentProvider) readerFactory; - } else if (readerFactory == null) { - fFileContentProvider= EmptyFilesProvider.getInstance(); - } else { - throw new IllegalArgumentException("Illegal reader factory"); //$NON-NLS-1$ - } - if (fileContent instanceof InternalFileContent) { - fRootContent= (InternalFileContent) fileContent; - } else { - throw new IllegalArgumentException("Illegal file content object"); //$NON-NLS-1$ - } - - fLog = AbstractParserLogService.convert(log); - fAdditionalNumericLiteralSuffixes= nonNull(configuration.supportAdditionalNumericLiteralSuffixes()); - fLexOptions.fSupportDollarInIdentifiers= configuration.support$InIdentifiers(); - fLexOptions.fSupportAtSignInIdentifiers= configuration.supportAtSignInIdentifiers(); - fLexOptions.fSupportMinAndMax = configuration.supportMinAndMaxOperators(); - fLexOptions.fSupportSlashPercentComments= configuration.supportSlashPercentComments(); - fLexOptions.fSupportUTFLiterals = configuration.supportUTFLiterals(); - fLexOptions.fSupportRawStringLiterals = configuration.supportRawStringLiterals(); - fLexOptions.fSupportUserDefinedLiterals = configuration.supportUserDefinedLiterals(); - fLexOptions.fSupportDigitSeparators = configuration.supportDigitSeparators(); - if (info instanceof ExtendedScannerInfo) - fLexOptions.fIncludeExportPatterns = ((ExtendedScannerInfo) info).getIncludeExportPatterns(); - fLocationMap= new LocationMap(fLexOptions); - fKeywords= new CharArrayIntMap(40, -1); - fPPKeywords= new CharArrayIntMap(40, -1); - configureKeywords(language, configuration); - - fExpressionEvaluator= new ExpressionEvaluator(this); - fMacroDefinitionParser= new MacroDefinitionParser(); - fMacroExpander= new MacroExpander(this, fMacroDictionary, fLocationMap, fLexOptions); - fIncludeFileResolutionHeuristics= fFileContentProvider.getIncludeHeuristics(); - - String contextPath= fFileContentProvider.getContextPath(); - if (contextPath == null) { - contextPath= fRootContent.getFileLocation(); - } - fIncludeSearchPath = configureIncludeSearchPath(new File(contextPath).getParentFile(), info); - setupMacroDictionary(configuration, info, language); - - ILocationCtx ctx= fLocationMap.pushTranslationUnit(fRootContent.getFileLocation(), fRootContent.getSource()); - Lexer lexer = new Lexer(fRootContent.getSource(), fLexOptions, this, this); - fRootContext= fCurrentContext= new ScannerContext(ctx, null, lexer); - if (info instanceof IExtendedScannerInfo) { - final IExtendedScannerInfo einfo= (IExtendedScannerInfo) info; - fPreIncludedFiles= new String[][] { einfo.getMacroFiles(), einfo.getIncludeFiles() }; - } - fFileContentProvider.resetForTranslationUnit(); - } - + if (readerFactory instanceof InternalFileContentProvider) { + fFileContentProvider = (InternalFileContentProvider) readerFactory; + } else if (readerFactory == null) { + fFileContentProvider = EmptyFilesProvider.getInstance(); + } else { + throw new IllegalArgumentException("Illegal reader factory"); //$NON-NLS-1$ + } + if (fileContent instanceof InternalFileContent) { + fRootContent = (InternalFileContent) fileContent; + } else { + throw new IllegalArgumentException("Illegal file content object"); //$NON-NLS-1$ + } + + fLog = AbstractParserLogService.convert(log); + fAdditionalNumericLiteralSuffixes = nonNull(configuration.supportAdditionalNumericLiteralSuffixes()); + fLexOptions.fSupportDollarInIdentifiers = configuration.support$InIdentifiers(); + fLexOptions.fSupportAtSignInIdentifiers = configuration.supportAtSignInIdentifiers(); + fLexOptions.fSupportMinAndMax = configuration.supportMinAndMaxOperators(); + fLexOptions.fSupportSlashPercentComments = configuration.supportSlashPercentComments(); + fLexOptions.fSupportUTFLiterals = configuration.supportUTFLiterals(); + fLexOptions.fSupportRawStringLiterals = configuration.supportRawStringLiterals(); + fLexOptions.fSupportUserDefinedLiterals = configuration.supportUserDefinedLiterals(); + fLexOptions.fSupportDigitSeparators = configuration.supportDigitSeparators(); + if (info instanceof ExtendedScannerInfo) + fLexOptions.fIncludeExportPatterns = ((ExtendedScannerInfo) info).getIncludeExportPatterns(); + fLocationMap = new LocationMap(fLexOptions); + fKeywords = new CharArrayIntMap(40, -1); + fPPKeywords = new CharArrayIntMap(40, -1); + configureKeywords(language, configuration); + + fExpressionEvaluator = new ExpressionEvaluator(this); + fMacroDefinitionParser = new MacroDefinitionParser(); + fMacroExpander = new MacroExpander(this, fMacroDictionary, fLocationMap, fLexOptions); + fIncludeFileResolutionHeuristics = fFileContentProvider.getIncludeHeuristics(); + + String contextPath = fFileContentProvider.getContextPath(); + if (contextPath == null) { + contextPath = fRootContent.getFileLocation(); + } + fIncludeSearchPath = configureIncludeSearchPath(new File(contextPath).getParentFile(), info); + setupMacroDictionary(configuration, info, language); + + ILocationCtx ctx = fLocationMap.pushTranslationUnit(fRootContent.getFileLocation(), fRootContent.getSource()); + Lexer lexer = new Lexer(fRootContent.getSource(), fLexOptions, this, this); + fRootContext = fCurrentContext = new ScannerContext(ctx, null, lexer); + if (info instanceof IExtendedScannerInfo) { + final IExtendedScannerInfo einfo = (IExtendedScannerInfo) info; + fPreIncludedFiles = new String[][] { einfo.getMacroFiles(), einfo.getIncludeFiles() }; + } + fFileContentProvider.resetForTranslationUnit(); + } + private char[] detectIncludeGuard(String filePath, AbstractCharArray source, ScannerContext ctx) { if (!fFileContentProvider.shouldIndexAllHeaderVersions(filePath)) { final char[] guard = IncludeGuardDetection.detectIncludeGuard(source, fLexOptions, fPPKeywords); if (guard != null) { - IFileNomination nom= fLocationMap.reportPragmaOnceSemantics(ctx.getLocationCtx()); + IFileNomination nom = fLocationMap.reportPragmaOnceSemantics(ctx.getLocationCtx()); fFileContentProvider.reportPragmaOnceSemantics(filePath, nom); ctx.internalModification(guard); ctx.setPragmaOnce(true); @@ -373,7 +372,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { if (ctx != fRootContext) { if (fLog.isTracing(TRACE_NO_GUARD)) { if (fTracedGuards == null) - fTracedGuards= new HashSet<>(); + fTracedGuards = new HashSet<>(); if (fTracedGuards.add(filePath)) fLog.traceLog(TRACE_NO_GUARD, "No include guard in " + filePath); //$NON-NLS-1$ } @@ -383,25 +382,25 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { @Override public void setSplitShiftROperator(boolean val) { - fSplitShiftRightOperator= val; - } + fSplitShiftRightOperator = val; + } @Override public void setComputeImageLocations(boolean val) { - fLexOptions.fCreateImageLocations= val; - } + fLexOptions.fCreateImageLocations = val; + } @Override public void setTrackIncludeExport(IncludeExportPatterns patterns) { - fLexOptions.fIncludeExportPatterns= patterns; - } + fLexOptions.fIncludeExportPatterns = patterns; + } @Override public void setContentAssistMode(int offset) { - fContentAssistLimit= offset; + fContentAssistLimit = offset; fRootContext.getLexer().setContentAssistMode(offset); } - + public boolean isContentAssistMode() { return fRootContext.getLexer().isContentAssistMode(); } @@ -423,7 +422,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { public ILocationResolver getLocationResolver() { return fLocationMap; } - + /** * @see IScannerExtensionConfiguration#supportAdditionalNumericLiteralSuffixes * @since 5.10 @@ -432,25 +431,25 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { public char[] getAdditionalNumericLiteralSuffixes() { return fAdditionalNumericLiteralSuffixes; } - + private void configureKeywords(ParserLanguage language, IScannerExtensionConfiguration configuration) { Keywords.addKeywordsPreprocessor(fPPKeywords); if (language == ParserLanguage.C) { - Keywords.addKeywordsC(fKeywords); - } else { - Keywords.addKeywordsCpp(fKeywords); - } - CharArrayIntMap additionalKeywords= configuration.getAdditionalKeywords(); - if (additionalKeywords != null) { - fKeywords.putAll(additionalKeywords); - } - additionalKeywords= configuration.getAdditionalPreprocessorKeywords(); - if (additionalKeywords != null) { - fPPKeywords.putAll(additionalKeywords); - } - } - - protected String getCurrentFilename() { + Keywords.addKeywordsC(fKeywords); + } else { + Keywords.addKeywordsCpp(fKeywords); + } + CharArrayIntMap additionalKeywords = configuration.getAdditionalKeywords(); + if (additionalKeywords != null) { + fKeywords.putAll(additionalKeywords); + } + additionalKeywords = configuration.getAdditionalPreprocessorKeywords(); + if (additionalKeywords != null) { + fPPKeywords.putAll(additionalKeywords); + } + } + + protected String getCurrentFilename() { return fLocationMap.getCurrentFilePath(); } @@ -459,43 +458,43 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } /** - * Returns include search path for a given current directory and a IScannerInfo. + * Returns include search path for a given current directory and a IScannerInfo. * @param directory the current directory * @param info scanner information, or {@code null} if not available * @return the include search path */ public static IncludeSearchPath configureIncludeSearchPath(File directory, IScannerInfo info) { - boolean inhibitUseOfCurrentFileDirectory= false; - List<IncludeSearchPathElement> elements = new ArrayList<>(); - - if (info != null) { - // Quote includes first - if (info instanceof IExtendedScannerInfo) { - final IExtendedScannerInfo einfo= (IExtendedScannerInfo) info; - final String[] paths= einfo.getLocalIncludePath(); - if (paths != null) { - for (String path : paths) { - if ("-".equals(path)) { //$NON-NLS-1$ - inhibitUseOfCurrentFileDirectory= true; - } else { - elements.add(new IncludeSearchPathElement(makeAbsolute(directory, path), true)); - } + boolean inhibitUseOfCurrentFileDirectory = false; + List<IncludeSearchPathElement> elements = new ArrayList<>(); + + if (info != null) { + // Quote includes first + if (info instanceof IExtendedScannerInfo) { + final IExtendedScannerInfo einfo = (IExtendedScannerInfo) info; + final String[] paths = einfo.getLocalIncludePath(); + if (paths != null) { + for (String path : paths) { + if ("-".equals(path)) { //$NON-NLS-1$ + inhibitUseOfCurrentFileDirectory = true; + } else { + elements.add(new IncludeSearchPathElement(makeAbsolute(directory, path), true)); + } + } + } + } + // Regular includes + String[] paths = info.getIncludePaths(); + if (paths != null) { + for (String path : paths) { + if ("-".equals(path)) { //$NON-NLS-1$ + inhibitUseOfCurrentFileDirectory = true; + } else { + elements.add(new IncludeSearchPathElement(makeAbsolute(directory, path), false)); } - } - } - // Regular includes - String[] paths= info.getIncludePaths(); - if (paths != null) { - for (String path : paths) { - if ("-".equals(path)) { //$NON-NLS-1$ - inhibitUseOfCurrentFileDirectory= true; - } else { - elements.add(new IncludeSearchPathElement(makeAbsolute(directory, path), false)); - } } - } - } - return new IncludeSearchPath(elements, inhibitUseOfCurrentFileDirectory); + } + } + return new IncludeSearchPath(elements, inhibitUseOfCurrentFileDirectory); } private static String makeAbsolute(File directory, String includePath) { @@ -505,56 +504,54 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return ScannerUtility.createReconciledPath(directory.getAbsolutePath(), includePath); } - private void setupMacroDictionary(IScannerExtensionConfiguration config, IScannerInfo info, - ParserLanguage lang) { - // Built-in macros - fMacroDictionary.put(__CDT_PARSER__.getNameCharArray(), __CDT_PARSER__); - fMacroDictionary.put(__STDC__.getNameCharArray(), __STDC__); - fMacroDictionary.put(__FILE__.getNameCharArray(), __FILE__); - fMacroDictionary.put(__DATE__.getNameCharArray(), __DATE__); - fMacroDictionary.put(__TIME__.getNameCharArray(), __TIME__); - fMacroDictionary.put(__LINE__.getNameCharArray(), __LINE__); - fMacroDictionary.put(__COUNTER__, new CounterMacro(__COUNTER__)); - - if (lang == ParserLanguage.CPP) { - fMacroDictionary.put(__cplusplus.getNameCharArray(), __cplusplus); - } else { - fMacroDictionary.put(__STDC_HOSTED__.getNameCharArray(), __STDC_HOSTED__); - fMacroDictionary.put(__STDC_VERSION__.getNameCharArray(), __STDC_VERSION__); - } - - IMacro[] toAdd = config.getAdditionalMacros(); - if (toAdd != null) { - for (final IMacro macro : toAdd) { - addMacroDefinition(macro.getSignature(), macro.getExpansion()); - } - } - - final Map<String, String> macroDict= info.getDefinedSymbols(); - if (macroDict != null) { - for (Map.Entry<String, String> entry : macroDict.entrySet()) { - final String key= entry.getKey(); - final String value= entry.getValue().trim(); + private void setupMacroDictionary(IScannerExtensionConfiguration config, IScannerInfo info, ParserLanguage lang) { + // Built-in macros + fMacroDictionary.put(__CDT_PARSER__.getNameCharArray(), __CDT_PARSER__); + fMacroDictionary.put(__STDC__.getNameCharArray(), __STDC__); + fMacroDictionary.put(__FILE__.getNameCharArray(), __FILE__); + fMacroDictionary.put(__DATE__.getNameCharArray(), __DATE__); + fMacroDictionary.put(__TIME__.getNameCharArray(), __TIME__); + fMacroDictionary.put(__LINE__.getNameCharArray(), __LINE__); + fMacroDictionary.put(__COUNTER__, new CounterMacro(__COUNTER__)); + + if (lang == ParserLanguage.CPP) { + fMacroDictionary.put(__cplusplus.getNameCharArray(), __cplusplus); + } else { + fMacroDictionary.put(__STDC_HOSTED__.getNameCharArray(), __STDC_HOSTED__); + fMacroDictionary.put(__STDC_VERSION__.getNameCharArray(), __STDC_VERSION__); + } + + IMacro[] toAdd = config.getAdditionalMacros(); + if (toAdd != null) { + for (final IMacro macro : toAdd) { + addMacroDefinition(macro.getSignature(), macro.getExpansion()); + } + } + + final Map<String, String> macroDict = info.getDefinedSymbols(); + if (macroDict != null) { + for (Map.Entry<String, String> entry : macroDict.entrySet()) { + final String key = entry.getKey(); + final String value = entry.getValue().trim(); addMacroDefinition(key.toCharArray(), value.toCharArray()); - } - } + } + } - Collection<PreprocessorMacro> predefined= fMacroDictionary.values(); - for (PreprocessorMacro macro : predefined) { - fLocationMap.registerPredefinedMacro(macro); + Collection<PreprocessorMacro> predefined = fMacroDictionary.values(); + for (PreprocessorMacro macro : predefined) { + fLocationMap.registerPredefinedMacro(macro); } - } + } private void beforeFirstFetchToken() { if (fPreIncludedFiles != null) { handlePreIncludedFiles(); - fPreIncludedFiles= null; + fPreIncludedFiles = null; } - final String location = fLocationMap.getTranslationUnitPath(); + final String location = fLocationMap.getTranslationUnitPath(); InternalFileContent content; try { - content = fFileContentProvider.getContentForContextToHeaderGap(location, - fMacroDictionaryFacade); + content = fFileContentProvider.getContentForContextToHeaderGap(location, fMacroDictionaryFacade); } catch (DependsOnOutdatedFileException e) { // Abort the parser, handled by the abstract indexer task. throw new RuntimeException(e); @@ -562,331 +559,331 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { if (content != null && content.getKind() == InclusionKind.FOUND_IN_INDEX) { processInclusionFromIndex(0, content, false); } - - detectIncludeGuard(location, fRootContent.getSource(), fRootContext); + + detectIncludeGuard(location, fRootContent.getSource(), fRootContext); fLocationMap.parsingFile(fFileContentProvider, fRootContent); - fRootContent= null; + fRootContent = null; } - private void handlePreIncludedFiles() { - final String[] imacro= fPreIncludedFiles[0]; - if (imacro != null && imacro.length > 0) { - final char[] buffer= createSyntheticFile(imacro); - ILocationCtx ctx= fLocationMap.pushPreInclusion(new CharArray(buffer), 0, true); - fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this)); - ScannerContext preCtx= fCurrentContext; - try { + private void handlePreIncludedFiles() { + final String[] imacro = fPreIncludedFiles[0]; + if (imacro != null && imacro.length > 0) { + final char[] buffer = createSyntheticFile(imacro); + ILocationCtx ctx = fLocationMap.pushPreInclusion(new CharArray(buffer), 0, true); + fCurrentContext = new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this)); + ScannerContext preCtx = fCurrentContext; + try { while (internalFetchToken(preCtx, CHECK_NUMBERS, false).getType() != IToken.tEND_OF_INPUT) { // just eat the tokens } - final ILocationCtx locationCtx = fCurrentContext.getLocationCtx(); - fLocationMap.popContext(locationCtx); - fCurrentContext= fCurrentContext.getParent(); - assert fCurrentContext == fRootContext; + final ILocationCtx locationCtx = fCurrentContext.getLocationCtx(); + fLocationMap.popContext(locationCtx); + fCurrentContext = fCurrentContext.getParent(); + assert fCurrentContext == fRootContext; } catch (OffsetLimitReachedException e) { } - } - final String[] include= fPreIncludedFiles[1]; - if (include != null && include.length > 0) { - final char[] buffer= createSyntheticFile(include); - ILocationCtx ctx= fLocationMap.pushPreInclusion(new CharArray(buffer), 0, false); - fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this)); - } - fPreIncludedFiles= null; - } + } + final String[] include = fPreIncludedFiles[1]; + if (include != null && include.length > 0) { + final char[] buffer = createSyntheticFile(include); + ILocationCtx ctx = fLocationMap.pushPreInclusion(new CharArray(buffer), 0, false); + fCurrentContext = new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this)); + } + fPreIncludedFiles = null; + } private char[] createSyntheticFile(String[] files) { - int totalLength= 0; - final char[] instruction= "#include <".toCharArray(); //$NON-NLS-1$ - for (String file : files) { - totalLength+= instruction.length + 2 + file.length(); - } - final char[] buffer= new char[totalLength]; - int pos= 0; - for (String file : files) { - final char[] fileName= file.toCharArray(); - System.arraycopy(instruction, 0, buffer, pos, instruction.length); - pos+= instruction.length; - System.arraycopy(fileName, 0, buffer, pos, fileName.length); - pos+= fileName.length; - buffer[pos++]= '>'; - buffer[pos++]= '\n'; - } - return buffer; - } - - public PreprocessorMacro addMacroDefinition(char[] key, char[] value) { - final Lexer lex= new Lexer(key, fLexOptions, ILexerLog.NULL, null); - try { - PreprocessorMacro result= fMacroDefinitionParser.parseMacroDefinition(lex, ILexerLog.NULL, value); - fLocationMap.registerPredefinedMacro(result); - fMacroDictionary.put(result.getNameCharArray(), result); - return result; - } catch (Exception e) { - fLog.traceLog("Invalid macro definition: '" + String.valueOf(key) + "'"); //$NON-NLS-1$//$NON-NLS-2$ - return null; - } - } - - @Override + int totalLength = 0; + final char[] instruction = "#include <".toCharArray(); //$NON-NLS-1$ + for (String file : files) { + totalLength += instruction.length + 2 + file.length(); + } + final char[] buffer = new char[totalLength]; + int pos = 0; + for (String file : files) { + final char[] fileName = file.toCharArray(); + System.arraycopy(instruction, 0, buffer, pos, instruction.length); + pos += instruction.length; + System.arraycopy(fileName, 0, buffer, pos, fileName.length); + pos += fileName.length; + buffer[pos++] = '>'; + buffer[pos++] = '\n'; + } + return buffer; + } + + public PreprocessorMacro addMacroDefinition(char[] key, char[] value) { + final Lexer lex = new Lexer(key, fLexOptions, ILexerLog.NULL, null); + try { + PreprocessorMacro result = fMacroDefinitionParser.parseMacroDefinition(lex, ILexerLog.NULL, value); + fLocationMap.registerPredefinedMacro(result); + fMacroDictionary.put(result.getNameCharArray(), result); + return result; + } catch (Exception e) { + fLog.traceLog("Invalid macro definition: '" + String.valueOf(key) + "'"); //$NON-NLS-1$//$NON-NLS-2$ + return null; + } + } + + @Override public Map<String, IMacroBinding> getMacroDefinitions() { - Map<String, IMacroBinding> hashMap = new HashMap<>(fMacroDictionary.size()); - for (char[] key : fMacroDictionary.keys()) { - hashMap.put(String.valueOf(key), fMacroDictionary.get(key)); + Map<String, IMacroBinding> hashMap = new HashMap<>(fMacroDictionary.size()); + for (char[] key : fMacroDictionary.keys()) { + hashMap.put(String.valueOf(key), fMacroDictionary.get(key)); } - return hashMap; - } + return hashMap; + } - @Override + @Override public boolean isOnTopContext() { - ScannerContext ctx= fCurrentContext; - while (ctx != null && ctx.getLocationCtx() instanceof LocationCtxMacroExpansion) { - ctx= ctx.getParent(); - } - return ctx == fRootContext; - } - - @Override + ScannerContext ctx = fCurrentContext; + while (ctx != null && ctx.getLocationCtx() instanceof LocationCtxMacroExpansion) { + ctx = ctx.getParent(); + } + return ctx == fRootContext; + } + + @Override public void cancel() { - isCancelled= true; - } - - /** - * Returns the next token from the preprocessor without concatenating string literals - * and also without splitting the shift-right operator. - */ - private Token fetchToken() throws OffsetLimitReachedException { - if (fIsFirstFetchToken) { - beforeFirstFetchToken(); - fIsFirstFetchToken= false; - } - Token t= fPrefetchedTokens; - if (t != null) { - fPrefetchedTokens= (Token) t.getNext(); - t.setNext(null); - return t; - } + isCancelled = true; + } + + /** + * Returns the next token from the preprocessor without concatenating string literals + * and also without splitting the shift-right operator. + */ + private Token fetchToken() throws OffsetLimitReachedException { + if (fIsFirstFetchToken) { + beforeFirstFetchToken(); + fIsFirstFetchToken = false; + } + Token t = fPrefetchedTokens; + if (t != null) { + fPrefetchedTokens = (Token) t.getNext(); + t.setNext(null); + return t; + } try { - t= internalFetchToken(fRootContext, CHECK_NUMBERS | REPORT_SIGNIFICANT_MACROS | IGNORE_UNDEFINED_SIGNIFICANT_MACROS, false); + t = internalFetchToken(fRootContext, + CHECK_NUMBERS | REPORT_SIGNIFICANT_MACROS | IGNORE_UNDEFINED_SIGNIFICANT_MACROS, false); } catch (OffsetLimitReachedException e) { - fHandledCompletion= true; + fHandledCompletion = true; throw e; } - final int offset= fLocationMap.getSequenceNumberForOffset(t.getOffset()); - final int endOffset= fLocationMap.getSequenceNumberForOffset(t.getEndOffset()); + final int offset = fLocationMap.getSequenceNumberForOffset(t.getOffset()); + final int endOffset = fLocationMap.getSequenceNumberForOffset(t.getEndOffset()); t.setOffset(offset, endOffset); t.setNext(null); - return t; - } - - private void pushbackToken(Token t) { - t.setNext(fPrefetchedTokens); - fPrefetchedTokens= t; - } - - /** - * Returns next token for the parser. String literals are not concatenated. When - * the end is reached tokens with type {@link IToken#tEND_OF_INPUT}. - * @throws OffsetLimitReachedException see {@link Lexer}. - */ - public IToken nextTokenRaw() throws OffsetLimitReachedException { - if (isCancelled) { - throw new ParseError(ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); - } - - Token t1= fetchToken(); - switch (t1.getType()) { - case IToken.tCOMPLETION: - fHandledCompletion= true; - break; - case IToken.tEND_OF_INPUT: - if (fContentAssistLimit >= 0) { - int useType= fHandledCompletion ? IToken.tEOC : IToken.tCOMPLETION; - int sequenceNumber= fLocationMap.getSequenceNumberForOffset(fContentAssistLimit); - t1= new Token(useType, null, sequenceNumber, sequenceNumber); - fHandledCompletion= true; - } - break; - case IToken.t_PRAGMA: - handlePragmaOperator(t1); - return nextTokenRaw(); - } - if (fLastToken != null) { - fLastToken.setNext(t1); - } - fLastToken= t1; - return t1; - } + return t; + } + + private void pushbackToken(Token t) { + t.setNext(fPrefetchedTokens); + fPrefetchedTokens = t; + } + + /** + * Returns next token for the parser. String literals are not concatenated. When + * the end is reached tokens with type {@link IToken#tEND_OF_INPUT}. + * @throws OffsetLimitReachedException see {@link Lexer}. + */ + public IToken nextTokenRaw() throws OffsetLimitReachedException { + if (isCancelled) { + throw new ParseError(ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); + } + + Token t1 = fetchToken(); + switch (t1.getType()) { + case IToken.tCOMPLETION: + fHandledCompletion = true; + break; + case IToken.tEND_OF_INPUT: + if (fContentAssistLimit >= 0) { + int useType = fHandledCompletion ? IToken.tEOC : IToken.tCOMPLETION; + int sequenceNumber = fLocationMap.getSequenceNumberForOffset(fContentAssistLimit); + t1 = new Token(useType, null, sequenceNumber, sequenceNumber); + fHandledCompletion = true; + } + break; + case IToken.t_PRAGMA: + handlePragmaOperator(t1); + return nextTokenRaw(); + } + if (fLastToken != null) { + fLastToken.setNext(t1); + } + fLastToken = t1; + return t1; + } private void handlePragmaOperator(Token t1) throws OffsetLimitReachedException { - Token t2= fetchToken(); + Token t2 = fetchToken(); int end; if (t2.getType() == IToken.tLPAREN) { - Token t3= fetchToken(); - end= t3.getEndOffset(); + Token t3 = fetchToken(); + end = t3.getEndOffset(); final int tt = t3.getType(); - if (tt == IToken.tSTRING || tt == IToken.tLSTRING || tt == IToken.tUTF16STRING || tt == IToken.tUTF32STRING) { - Token t4= fetchToken(); - end= t4.getEndOffset(); + if (tt == IToken.tSTRING || tt == IToken.tLSTRING || tt == IToken.tUTF16STRING + || tt == IToken.tUTF32STRING) { + Token t4 = fetchToken(); + end = t4.getEndOffset(); if (t4.getType() == IToken.tRPAREN) { - fLocationMap.encounterPragmaOperator(t1.getOffset(), t3.getOffset(), - t3.getEndOffset(), t4.getEndOffset()); + fLocationMap.encounterPragmaOperator(t1.getOffset(), t3.getOffset(), t3.getEndOffset(), + t4.getEndOffset()); return; } else { - end= t3.getEndOffset(); + end = t3.getEndOffset(); pushbackToken(t4); } } else { if (t3.getType() == IToken.tRPAREN) { // Consume closing parenthesis - end= t3.getEndOffset(); + end = t3.getEndOffset(); } else { - end= t2.getEndOffset(); + end = t2.getEndOffset(); pushbackToken(t3); } } } else { - end= t1.getEndOffset(); + end = t1.getEndOffset(); pushbackToken(t2); - } - fLocationMap.encounterProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, t1.getCharImage(), - t1.getOffset(), end); + } + fLocationMap.encounterProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, t1.getCharImage(), t1.getOffset(), end); } - /** - * Returns next token for the parser. String literals are concatenated. - * @throws EndOfFileException when the end of the translation unit has been reached. - * @throws OffsetLimitReachedException see {@link Lexer}. - */ - @Override + /** + * Returns next token for the parser. String literals are concatenated. + * @throws EndOfFileException when the end of the translation unit has been reached. + * @throws OffsetLimitReachedException see {@link Lexer}. + */ + @Override public IToken nextToken() throws EndOfFileException { - if (isCancelled) { - throw new ParseError(ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); - } - - Token t1= fetchToken(); - char[] udlSuffix = null; - - final int tt1= t1.getType(); - switch (tt1) { - case IToken.tCOMPLETION: - fHandledCompletion= true; - break; - - case IToken.tEND_OF_INPUT: - if (fContentAssistLimit < 0) { - fPrefetchedTokens= t1; - throw new EndOfFileException(t1.getOffset()); - } - int useType= fHandledCompletion ? IToken.tEOC : IToken.tCOMPLETION; - int sequenceNumber= fLocationMap.getSequenceNumberForOffset(fContentAssistLimit); - t1= new Token(useType, null, sequenceNumber, sequenceNumber); - fHandledCompletion= true; - break; - - case IToken.t_PRAGMA: - handlePragmaOperator(t1); - return nextToken(); - case IToken.tUSER_DEFINED_STRING_LITERAL: - udlSuffix = getUserDefinedLiteralSuffix(t1); - //$FALL-THROUGH$ - case IToken.tSTRING: - case IToken.tLSTRING: - case IToken.tUTF16STRING: - case IToken.tUTF32STRING: - StringType st = StringType.fromToken(t1); - Token t2; - StringBuilder buf= null; - int endOffset= t1.getEndOffset(); - loop: while (true) { - t2= fetchToken(); - final int tt2= t2.getType(); - switch (tt2) { - case IToken.tUSER_DEFINED_STRING_LITERAL: - if (udlSuffix == null) { - udlSuffix = getUserDefinedLiteralSuffix(t2); - } else if (!Arrays.equals(udlSuffix, getUserDefinedLiteralSuffix(t2))) { - handleProblem(IProblem.PREPROCESSOR_MULTIPLE_USER_DEFINED_SUFFIXES_IN_CONCATENATION, - udlSuffix, t2.getOffset(), endOffset); - } + if (isCancelled) { + throw new ParseError(ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); + } + + Token t1 = fetchToken(); + char[] udlSuffix = null; + + final int tt1 = t1.getType(); + switch (tt1) { + case IToken.tCOMPLETION: + fHandledCompletion = true; + break; + + case IToken.tEND_OF_INPUT: + if (fContentAssistLimit < 0) { + fPrefetchedTokens = t1; + throw new EndOfFileException(t1.getOffset()); + } + int useType = fHandledCompletion ? IToken.tEOC : IToken.tCOMPLETION; + int sequenceNumber = fLocationMap.getSequenceNumberForOffset(fContentAssistLimit); + t1 = new Token(useType, null, sequenceNumber, sequenceNumber); + fHandledCompletion = true; + break; + + case IToken.t_PRAGMA: + handlePragmaOperator(t1); + return nextToken(); + case IToken.tUSER_DEFINED_STRING_LITERAL: + udlSuffix = getUserDefinedLiteralSuffix(t1); + //$FALL-THROUGH$ + case IToken.tSTRING: + case IToken.tLSTRING: + case IToken.tUTF16STRING: + case IToken.tUTF32STRING: + StringType st = StringType.fromToken(t1); + Token t2; + StringBuilder buf = null; + int endOffset = t1.getEndOffset(); + loop: while (true) { + t2 = fetchToken(); + final int tt2 = t2.getType(); + switch (tt2) { + case IToken.tUSER_DEFINED_STRING_LITERAL: + if (udlSuffix == null) { + udlSuffix = getUserDefinedLiteralSuffix(t2); + } else if (!Arrays.equals(udlSuffix, getUserDefinedLiteralSuffix(t2))) { + handleProblem(IProblem.PREPROCESSOR_MULTIPLE_USER_DEFINED_SUFFIXES_IN_CONCATENATION, udlSuffix, + t2.getOffset(), endOffset); + } //$FALL-THROUGH$ case IToken.tLSTRING: - case IToken.tSTRING: - case IToken.tUTF16STRING: - case IToken.tUTF32STRING: - st = StringType.max(st, StringType.fromToken(t2)); - if (buf == null) { - buf= new StringBuilder(); - appendStringContent(buf, t1); - } - appendStringContent(buf, t2); - endOffset= t2.getEndOffset(); - continue loop; - case IToken.tINACTIVE_CODE_START: - // no support for inactive code after a string literal - skipInactiveCode(); - continue loop; - case IToken.t_PRAGMA: - handlePragmaOperator(t2); - continue loop; + case IToken.tSTRING: + case IToken.tUTF16STRING: + case IToken.tUTF32STRING: + st = StringType.max(st, StringType.fromToken(t2)); + if (buf == null) { + buf = new StringBuilder(); + appendStringContent(buf, t1); + } + appendStringContent(buf, t2); + endOffset = t2.getEndOffset(); + continue loop; + case IToken.tINACTIVE_CODE_START: + // no support for inactive code after a string literal + skipInactiveCode(); + continue loop; + case IToken.t_PRAGMA: + handlePragmaOperator(t2); + continue loop; default: - break loop; - } - } - pushbackToken(t2); - if (buf != null) { - char[] prefix = st.getPrefix(); - final int imageLength = buf.length() + prefix.length + 2 + (udlSuffix == null ? 0 : udlSuffix.length); - char[] image= new char[imageLength]; - int off= -1; - int tokenType = st.getTokenValue(); - - for (char c : prefix) - image[++off] = c; - - image[++off]= '"'; - buf.getChars(0, buf.length(), image, ++off); - off += buf.length(); - image[off]= '"'; - if (udlSuffix != null) { - System.arraycopy(udlSuffix, 0, image, ++off, udlSuffix.length); - tokenType = IToken.tUSER_DEFINED_STRING_LITERAL; - } - t1= new TokenWithImage(tokenType, null, t1.getOffset(), endOffset, image); - } - break; - - case IToken.tSHIFTR: - if (fSplitShiftRightOperator) { - int offset= t1.getOffset(); - endOffset= t1.getEndOffset(); - - t1.setType(IToken.tGT_in_SHIFTR); - t1.setOffset(offset, offset + 1); - t2= new Token(IToken.tGT_in_SHIFTR, t1.fSource, offset + 1, endOffset); - pushbackToken(t2); - } - } - - if (fLastToken != null) { - fLastToken.setNext(t1); - } - fLastToken= t1; - return t1; - } - - @Override - public void skipInactiveCode() throws OffsetLimitReachedException { - final Lexer lexer= fCurrentContext.getLexer(); - if (lexer != null) { - CodeState state= fCurrentContext.getCodeState(); - while (state != CodeState.eActive) { - state= skipBranch(lexer, false); - } - fCurrentContext.clearInactiveCodeMarkerToken(); - } + break loop; + } + } + pushbackToken(t2); + if (buf != null) { + char[] prefix = st.getPrefix(); + final int imageLength = buf.length() + prefix.length + 2 + (udlSuffix == null ? 0 : udlSuffix.length); + char[] image = new char[imageLength]; + int off = -1; + int tokenType = st.getTokenValue(); + + for (char c : prefix) + image[++off] = c; + + image[++off] = '"'; + buf.getChars(0, buf.length(), image, ++off); + off += buf.length(); + image[off] = '"'; + if (udlSuffix != null) { + System.arraycopy(udlSuffix, 0, image, ++off, udlSuffix.length); + tokenType = IToken.tUSER_DEFINED_STRING_LITERAL; + } + t1 = new TokenWithImage(tokenType, null, t1.getOffset(), endOffset, image); + } + break; + + case IToken.tSHIFTR: + if (fSplitShiftRightOperator) { + int offset = t1.getOffset(); + endOffset = t1.getEndOffset(); + + t1.setType(IToken.tGT_in_SHIFTR); + t1.setOffset(offset, offset + 1); + t2 = new Token(IToken.tGT_in_SHIFTR, t1.fSource, offset + 1, endOffset); + pushbackToken(t2); + } + } + + if (fLastToken != null) { + fLastToken.setNext(t1); + } + fLastToken = t1; + return t1; } + @Override + public void skipInactiveCode() throws OffsetLimitReachedException { + final Lexer lexer = fCurrentContext.getLexer(); + if (lexer != null) { + CodeState state = fCurrentContext.getCodeState(); + while (state != CodeState.eActive) { + state = skipBranch(lexer, false); + } + fCurrentContext.clearInactiveCodeMarkerToken(); + } + } @Override public int getCodeBranchNesting() { @@ -894,124 +891,122 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } private void appendStringContent(StringBuilder buf, Token t1) { - final char[] image= t1.getCharImage(); - final int length= image.length; - int start = 1; - for (char c : image) { - if (c == '"') - break; - start++; - } - - if (length > 1) { - int diff = 0; - if (t1.getType() == IToken.tUSER_DEFINED_STRING_LITERAL) { - diff = t1.getImage().lastIndexOf('"') - start; - } else { - diff= image[length - 1] == '"' ? length - start - 1 : length - start; - } - if (diff > 0) { - buf.append(image, start, diff); - } - } + final char[] image = t1.getCharImage(); + final int length = image.length; + int start = 1; + for (char c : image) { + if (c == '"') + break; + start++; + } + + if (length > 1) { + int diff = 0; + if (t1.getType() == IToken.tUSER_DEFINED_STRING_LITERAL) { + diff = t1.getImage().lastIndexOf('"') - start; + } else { + diff = image[length - 1] == '"' ? length - start - 1 : length - start; + } + if (diff > 0) { + buf.append(image, start, diff); + } + } } Token internalFetchToken(final ScannerContext uptoEndOfCtx, int options, boolean withinExpansion) throws OffsetLimitReachedException { - - - Token ppToken= fCurrentContext.currentLexerToken(); - while (true) { + + Token ppToken = fCurrentContext.currentLexerToken(); + while (true) { switch (ppToken.getType()) { - case Lexer.tBEFORE_INPUT: - ppToken= fCurrentContext.nextPPToken(); - continue; - - case Lexer.tNEWLINE: - if ((options & STOP_AT_NL) != 0) { - return ppToken; - } - ppToken= fCurrentContext.nextPPToken(); - continue; - - case Lexer.tOTHER_CHARACTER: - handleProblem(IProblem.SCANNER_BAD_CHARACTER, ppToken.getCharImage(), - ppToken.getOffset(), ppToken.getEndOffset()); - ppToken= fCurrentContext.nextPPToken(); - continue; - - case IToken.tEND_OF_INPUT: - if (fCurrentContext == uptoEndOfCtx || uptoEndOfCtx == null) { - if (fCurrentContext == fRootContext && !fHandledEndOfTranslationUnit - && (options & STOP_AT_NL) == 0) { - fHandledEndOfTranslationUnit= true; - fLocationMap.endTranslationUnit(ppToken.getEndOffset(), fCurrentContext.getSignificantMacros()); - } - return ppToken; - } - - final ILocationCtx locationCtx = fCurrentContext.getLocationCtx(); - ASTInclusionStatement inc = locationCtx.getInclusionStatement(); - if (inc != null) { - completeInclusion(inc); - } - fLocationMap.popContext(locationCtx); - - fCurrentContext.propagateSignificantMacros(); - fCurrentContext= fCurrentContext.getParent(); - assert fCurrentContext != null; - - ppToken= fCurrentContext.currentLexerToken(); - continue; - - case IToken.tPOUND: - { - final Lexer lexer= fCurrentContext.getLexer(); - if (lexer != null && lexer.currentTokenIsFirstOnLine()) { - executeDirective(lexer, ppToken.getOffset(), withinExpansion); - ppToken= fCurrentContext.currentLexerToken(); - continue; - } - break; - } - - case IToken.tIDENTIFIER: - fCurrentContext.nextPPToken(); // consume the identifier - if ((options & NO_EXPANSION) == 0) { - final Lexer lexer= fCurrentContext.getLexer(); - if (lexer != null && expandMacro(ppToken, lexer, options, withinExpansion)) { - ppToken= fCurrentContext.currentLexerToken(); - continue; - } - - final char[] name= ppToken.getCharImage(); - int tokenType = fKeywords.get(name); - if (tokenType != fKeywords.undefined) { - ppToken.setType(tokenType); - } - } - return ppToken; - - case IToken.tINTEGER: - if ((options & CHECK_NUMBERS) != 0) { - checkNumber(ppToken, false); - } - break; - - case IToken.tFLOATINGPT: - if ((options & CHECK_NUMBERS) != 0) { - checkNumber(ppToken, true); - } - break; - } + case Lexer.tBEFORE_INPUT: + ppToken = fCurrentContext.nextPPToken(); + continue; + + case Lexer.tNEWLINE: + if ((options & STOP_AT_NL) != 0) { + return ppToken; + } + ppToken = fCurrentContext.nextPPToken(); + continue; + + case Lexer.tOTHER_CHARACTER: + handleProblem(IProblem.SCANNER_BAD_CHARACTER, ppToken.getCharImage(), ppToken.getOffset(), + ppToken.getEndOffset()); + ppToken = fCurrentContext.nextPPToken(); + continue; + + case IToken.tEND_OF_INPUT: + if (fCurrentContext == uptoEndOfCtx || uptoEndOfCtx == null) { + if (fCurrentContext == fRootContext && !fHandledEndOfTranslationUnit + && (options & STOP_AT_NL) == 0) { + fHandledEndOfTranslationUnit = true; + fLocationMap.endTranslationUnit(ppToken.getEndOffset(), fCurrentContext.getSignificantMacros()); + } + return ppToken; + } + + final ILocationCtx locationCtx = fCurrentContext.getLocationCtx(); + ASTInclusionStatement inc = locationCtx.getInclusionStatement(); + if (inc != null) { + completeInclusion(inc); + } + fLocationMap.popContext(locationCtx); + + fCurrentContext.propagateSignificantMacros(); + fCurrentContext = fCurrentContext.getParent(); + assert fCurrentContext != null; + + ppToken = fCurrentContext.currentLexerToken(); + continue; + + case IToken.tPOUND: { + final Lexer lexer = fCurrentContext.getLexer(); + if (lexer != null && lexer.currentTokenIsFirstOnLine()) { + executeDirective(lexer, ppToken.getOffset(), withinExpansion); + ppToken = fCurrentContext.currentLexerToken(); + continue; + } + break; + } + + case IToken.tIDENTIFIER: + fCurrentContext.nextPPToken(); // consume the identifier + if ((options & NO_EXPANSION) == 0) { + final Lexer lexer = fCurrentContext.getLexer(); + if (lexer != null && expandMacro(ppToken, lexer, options, withinExpansion)) { + ppToken = fCurrentContext.currentLexerToken(); + continue; + } + + final char[] name = ppToken.getCharImage(); + int tokenType = fKeywords.get(name); + if (tokenType != fKeywords.undefined) { + ppToken.setType(tokenType); + } + } + return ppToken; + + case IToken.tINTEGER: + if ((options & CHECK_NUMBERS) != 0) { + checkNumber(ppToken, false); + } + break; + + case IToken.tFLOATINGPT: + if ((options & CHECK_NUMBERS) != 0) { + checkNumber(ppToken, true); + } + break; + } fCurrentContext.nextPPToken(); - return ppToken; - } - } + return ppToken; + } + } private void completeInclusion(ASTInclusionStatement inc) { final ISignificantMacros sig; - CharArrayObjectMap<char[]> sigMacros= fCurrentContext.getSignificantMacros(); + CharArrayObjectMap<char[]> sigMacros = fCurrentContext.getSignificantMacros(); if (sigMacros == null || sigMacros.isEmpty()) { sig = ISignificantMacros.NONE; } else { @@ -1024,273 +1019,378 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } private void checkNumber(Token number, final boolean isFloat) { - final char[] image= number.getCharImage(); - boolean hasExponent = false; - - // Integer constants written in binary are a non-standard extension - // supported by GCC since 4.3 and by some other C compilers - // They consist of a prefix 0b or 0B, followed by a sequence of 0 and 1 digits - // see http://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html - boolean isBin = false; - - boolean isHex = false; - boolean isOctal = false; - boolean hasDot= false; - - boolean badSuffix = false; - - int pos= 0; - if (image.length > 1) { - if (image[0] == '0') { - switch (image[++pos]) { - case 'b': - case 'B': - isBin = true; - ++pos; - break; - case 'x': - case 'X': - isHex = true; - ++pos; - break; - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': - if (!isFloat) - isOctal = true; - ++pos; - break; - case '8': case '9': - if (!isFloat) { - handleProblem(IProblem.SCANNER_BAD_OCTAL_FORMAT, image, number.getOffset(), number.getEndOffset()); - return; - } - ++pos; - break; - } - } - } - - loop: for (; pos < image.length; pos++) { - if (isBin) { - switch (image[pos]) { - case '0': case'1': - continue; - case '\'': - if (fLexOptions.fSupportDigitSeparators) { - continue; - } else { - break loop; - } - case 'e': case 'E': - case '.': - handleProblem(IProblem.SCANNER_FLOAT_WITH_BAD_PREFIX, "0b".toCharArray(), number.getOffset(), number.getEndOffset()); //$NON-NLS-1$ - return; - default: - // 0 and 1 are the only allowed digits for binary integers - // No floating point, exponents etc. are allowed - break loop; - } - } - switch (image[pos]) { - // octal digits - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': - continue; - - // decimal digits - case '8': case '9': - if (isOctal) { - handleProblem(IProblem.SCANNER_BAD_OCTAL_FORMAT, image, number.getOffset(), number.getEndOffset()); - return; - } - continue; - - // hex digits - case 'a': case 'A': case 'b': case 'B': case 'c': case 'C': case 'd': case 'D': case 'f': case 'F': - if (isHex && !hasExponent) { - continue; - } - break loop; - - case '.': - if (hasDot) { - handleProblem(IProblem.SCANNER_BAD_FLOATING_POINT, image, number.getOffset(), number.getEndOffset()); - return; - } - hasDot= true; - continue; - - // C++14 literal separator - case '\'': - if (fLexOptions.fSupportDigitSeparators) { - continue; - } else { - break loop; - } - - // check for exponent or hex digit - case 'E': case 'e': - if (isHex && !hasExponent) { - continue; - } - if (isFloat && !isHex && !hasExponent && pos+1 < image.length) { - switch (image[pos+1]) { - case '+': case '-': - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - hasExponent = true; - ++pos; - continue; - } - } - break loop; - - // check for hex float exponent - case 'p': case 'P': - if (isFloat && isHex && !hasExponent && pos+1 < image.length) { - switch (image[pos+1]) { - case '+': case '-': - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - hasExponent = true; - ++pos; - continue; - } - } - break loop; - - default: - break loop; - } - } - if (pos < image.length) { - char c = image[pos]; - if (Character.isLetter(c) || c == '_') { - // check the suffix - final int suffixStart = pos; - loop: for (; pos < image.length; pos++) { - c= image[pos]; - switch (c) { - case 'u': case 'U': case 'L': case 'l': - continue; - case 'f': case 'F': - if (isFloat) { - continue loop; - } - - //$FALL-THROUGH$ - case 'a': case 'b': case 'c': case 'd': case 'e': case 'g': case 'h': case 'i': - case 'j': case 'k': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': - case 's': case 't': case 'v': case 'w': case 'x': case 'y': case 'z': - case 'A': case 'B': case 'C': case 'D': case 'E': case 'G': case 'H': case 'I': - case 'J': case 'K': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': - case 'S': case 'T':case 'V': case 'W': case 'X': case 'Y': case 'Z': - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case '_': - if (fLexOptions.fSupportUserDefinedLiterals) { - continue loop; - } - } - for (int i= 0; i < fAdditionalNumericLiteralSuffixes.length; i++) { - if (fAdditionalNumericLiteralSuffixes[i] == c) { - continue loop; - } else { - badSuffix = true; - } - } - - if (badSuffix) { - char[] suffix = CharArrayUtils.subarray(image, suffixStart, -1); - handleProblem(IProblem.SCANNER_CONSTANT_WITH_BAD_SUFFIX, suffix, number.getOffset(), number.getEndOffset()); - return; - } - } - return; - } - } - else { - return; - } - - if (isBin) { - // The check for bin has to come before float, otherwise binary integers - // with float components get flagged as BAD_FLOATING_POINT - handleProblem(IProblem.SCANNER_BAD_BINARY_FORMAT, image, number.getOffset(), number.getEndOffset()); - } else if (isFloat) { - handleProblem(IProblem.SCANNER_BAD_FLOATING_POINT, image, number.getOffset(), number.getEndOffset()); - } else if (isHex) { - handleProblem(IProblem.SCANNER_BAD_HEX_FORMAT, image, number.getOffset(), number.getEndOffset()); - } else if (isOctal) { - handleProblem(IProblem.SCANNER_BAD_OCTAL_FORMAT, image, number.getOffset(), number.getEndOffset()); - } else { - handleProblem(IProblem.SCANNER_BAD_DECIMAL_FORMAT, image, number.getOffset(), number.getEndOffset()); - } - return; - - } - - private <T> T findInclusion(final String includeDirective, final boolean quoteInclude, - final boolean includeNext, final String currentFile, final IIncludeFileTester<T> tester) { - T reader = null; - String absoluteInclusionPath = getAbsoluteInclusionPath(includeDirective, currentFile); - if (absoluteInclusionPath != null) { - return tester.checkFile(absoluteInclusionPath, false, null); - } - - if (currentFile != null && quoteInclude && !includeNext && !fIncludeSearchPath.isInhibitUseOfCurrentFileDirectory()) { - // Check to see if we find a match in the directory of the current file - final File currentDir= new File(currentFile).getParentFile(); - if (currentDir != null) { - final String fileLocation = ScannerUtility.createReconciledPath( - currentDir.getAbsolutePath(), includeDirective); - reader = tester.checkFile(fileLocation, false, null); - if (reader != null) { - return reader; - } - } - } - - // Now we need to search for the file on the include search path. - // If this is a include_next directive then the search starts with the directory - // in the search path after the one where the current file was found. - IncludeSearchPathElement searchAfter= null; - if (includeNext && currentFile != null) { - searchAfter = fCurrentContext.getFoundOnPath(); - if (searchAfter == null) { - // the current file was found without search path - String directive= fCurrentContext.getFoundViaDirective(); - if (directive == null) { - directive= new File(currentFile).getName(); - } - searchAfter = findFileInIncludePath(currentFile, directive); - } - } - - for (IncludeSearchPathElement path : fIncludeSearchPath.getElements()) { - if (searchAfter != null) { - if (searchAfter.equals(path)) { - searchAfter= null; - } - } else if (quoteInclude || !path.isForQuoteIncludesOnly()) { - String fileLocation = path.getLocation(includeDirective); - if (fileLocation != null) { - reader= tester.checkFile(fileLocation, false, path); - if (reader != null) { - return reader; - } - } - } - } - if (fIncludeFileResolutionHeuristics != null) { - String location= fIncludeFileResolutionHeuristics.findInclusion(includeDirective, currentFile); - if (location != null) { - return tester.checkFile(location, true, null); - } - } - return null; - } - - public static String getAbsoluteInclusionPath(String includeDirective, String currentFile) { + final char[] image = number.getCharImage(); + boolean hasExponent = false; + + // Integer constants written in binary are a non-standard extension + // supported by GCC since 4.3 and by some other C compilers + // They consist of a prefix 0b or 0B, followed by a sequence of 0 and 1 digits + // see http://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html + boolean isBin = false; + + boolean isHex = false; + boolean isOctal = false; + boolean hasDot = false; + + boolean badSuffix = false; + + int pos = 0; + if (image.length > 1) { + if (image[0] == '0') { + switch (image[++pos]) { + case 'b': + case 'B': + isBin = true; + ++pos; + break; + case 'x': + case 'X': + isHex = true; + ++pos; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + if (!isFloat) + isOctal = true; + ++pos; + break; + case '8': + case '9': + if (!isFloat) { + handleProblem(IProblem.SCANNER_BAD_OCTAL_FORMAT, image, number.getOffset(), + number.getEndOffset()); + return; + } + ++pos; + break; + } + } + } + + loop: for (; pos < image.length; pos++) { + if (isBin) { + switch (image[pos]) { + case '0': + case '1': + continue; + case '\'': + if (fLexOptions.fSupportDigitSeparators) { + continue; + } else { + break loop; + } + case 'e': + case 'E': + case '.': + handleProblem(IProblem.SCANNER_FLOAT_WITH_BAD_PREFIX, "0b".toCharArray(), number.getOffset(), //$NON-NLS-1$ + number.getEndOffset()); + return; + default: + // 0 and 1 are the only allowed digits for binary integers + // No floating point, exponents etc. are allowed + break loop; + } + } + switch (image[pos]) { + // octal digits + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + continue; + + // decimal digits + case '8': + case '9': + if (isOctal) { + handleProblem(IProblem.SCANNER_BAD_OCTAL_FORMAT, image, number.getOffset(), number.getEndOffset()); + return; + } + continue; + + // hex digits + case 'a': + case 'A': + case 'b': + case 'B': + case 'c': + case 'C': + case 'd': + case 'D': + case 'f': + case 'F': + if (isHex && !hasExponent) { + continue; + } + break loop; + + case '.': + if (hasDot) { + handleProblem(IProblem.SCANNER_BAD_FLOATING_POINT, image, number.getOffset(), + number.getEndOffset()); + return; + } + hasDot = true; + continue; + + // C++14 literal separator + case '\'': + if (fLexOptions.fSupportDigitSeparators) { + continue; + } else { + break loop; + } + + // check for exponent or hex digit + case 'E': + case 'e': + if (isHex && !hasExponent) { + continue; + } + if (isFloat && !isHex && !hasExponent && pos + 1 < image.length) { + switch (image[pos + 1]) { + case '+': + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + hasExponent = true; + ++pos; + continue; + } + } + break loop; + + // check for hex float exponent + case 'p': + case 'P': + if (isFloat && isHex && !hasExponent && pos + 1 < image.length) { + switch (image[pos + 1]) { + case '+': + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + hasExponent = true; + ++pos; + continue; + } + } + break loop; + + default: + break loop; + } + } + if (pos < image.length) { + char c = image[pos]; + if (Character.isLetter(c) || c == '_') { + // check the suffix + final int suffixStart = pos; + loop: for (; pos < image.length; pos++) { + c = image[pos]; + switch (c) { + case 'u': + case 'U': + case 'L': + case 'l': + continue; + case 'f': + case 'F': + if (isFloat) { + continue loop; + } + + //$FALL-THROUGH$ + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '_': + if (fLexOptions.fSupportUserDefinedLiterals) { + continue loop; + } + } + for (int i = 0; i < fAdditionalNumericLiteralSuffixes.length; i++) { + if (fAdditionalNumericLiteralSuffixes[i] == c) { + continue loop; + } else { + badSuffix = true; + } + } + + if (badSuffix) { + char[] suffix = CharArrayUtils.subarray(image, suffixStart, -1); + handleProblem(IProblem.SCANNER_CONSTANT_WITH_BAD_SUFFIX, suffix, number.getOffset(), + number.getEndOffset()); + return; + } + } + return; + } + } else { + return; + } + + if (isBin) { + // The check for bin has to come before float, otherwise binary integers + // with float components get flagged as BAD_FLOATING_POINT + handleProblem(IProblem.SCANNER_BAD_BINARY_FORMAT, image, number.getOffset(), number.getEndOffset()); + } else if (isFloat) { + handleProblem(IProblem.SCANNER_BAD_FLOATING_POINT, image, number.getOffset(), number.getEndOffset()); + } else if (isHex) { + handleProblem(IProblem.SCANNER_BAD_HEX_FORMAT, image, number.getOffset(), number.getEndOffset()); + } else if (isOctal) { + handleProblem(IProblem.SCANNER_BAD_OCTAL_FORMAT, image, number.getOffset(), number.getEndOffset()); + } else { + handleProblem(IProblem.SCANNER_BAD_DECIMAL_FORMAT, image, number.getOffset(), number.getEndOffset()); + } + return; + + } + + private <T> T findInclusion(final String includeDirective, final boolean quoteInclude, final boolean includeNext, + final String currentFile, final IIncludeFileTester<T> tester) { + T reader = null; + String absoluteInclusionPath = getAbsoluteInclusionPath(includeDirective, currentFile); + if (absoluteInclusionPath != null) { + return tester.checkFile(absoluteInclusionPath, false, null); + } + + if (currentFile != null && quoteInclude && !includeNext + && !fIncludeSearchPath.isInhibitUseOfCurrentFileDirectory()) { + // Check to see if we find a match in the directory of the current file + final File currentDir = new File(currentFile).getParentFile(); + if (currentDir != null) { + final String fileLocation = ScannerUtility.createReconciledPath(currentDir.getAbsolutePath(), + includeDirective); + reader = tester.checkFile(fileLocation, false, null); + if (reader != null) { + return reader; + } + } + } + + // Now we need to search for the file on the include search path. + // If this is a include_next directive then the search starts with the directory + // in the search path after the one where the current file was found. + IncludeSearchPathElement searchAfter = null; + if (includeNext && currentFile != null) { + searchAfter = fCurrentContext.getFoundOnPath(); + if (searchAfter == null) { + // the current file was found without search path + String directive = fCurrentContext.getFoundViaDirective(); + if (directive == null) { + directive = new File(currentFile).getName(); + } + searchAfter = findFileInIncludePath(currentFile, directive); + } + } + + for (IncludeSearchPathElement path : fIncludeSearchPath.getElements()) { + if (searchAfter != null) { + if (searchAfter.equals(path)) { + searchAfter = null; + } + } else if (quoteInclude || !path.isForQuoteIncludesOnly()) { + String fileLocation = path.getLocation(includeDirective); + if (fileLocation != null) { + reader = tester.checkFile(fileLocation, false, path); + if (reader != null) { + return reader; + } + } + } + } + if (fIncludeFileResolutionHeuristics != null) { + String location = fIncludeFileResolutionHeuristics.findInclusion(includeDirective, currentFile); + if (location != null) { + return tester.checkFile(location, true, null); + } + } + return null; + } + + public static String getAbsoluteInclusionPath(String includeDirective, String currentFile) { // Filename is an absolute path. if (new File(includeDirective).isAbsolute()) { - return includeDirective; + return includeDirective; } // Filename is a Linux absolute path on a Windows machine. if (File.separatorChar == '\\' && !includeDirective.isEmpty()) { @@ -1299,254 +1399,252 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { if (currentFile != null && currentFile.length() > 1 && currentFile.charAt(1) == ':') { return currentFile.substring(0, 2) + includeDirective; } - return includeDirective; + return includeDirective; + } + } + return null; + } + + private IncludeSearchPathElement findFileInIncludePath(String file, String includeDirective) { + for (IncludeSearchPathElement path : fIncludeSearchPath.getElements()) { + String fileLocation = path.getLocation(includeDirective); + if (file.equals(fileLocation)) { + return path; } } return null; - } - - private IncludeSearchPathElement findFileInIncludePath(String file, String includeDirective) { - for (IncludeSearchPathElement path : fIncludeSearchPath.getElements()) { - String fileLocation = path.getLocation(includeDirective); - if (file.equals(fileLocation)) { - return path; - } - } - return null; - } - - @Override + } + + @Override public String toString() { - StringBuilder buffer = new StringBuilder("Scanner @ file:"); //$NON-NLS-1$ - buffer.append(fCurrentContext.toString()); - buffer.append(" line: "); //$NON-NLS-1$ - buffer.append(fLocationMap.getCurrentLineNumber(fCurrentContext.currentLexerToken().getOffset())); - return buffer.toString(); - } - - private void addMacroDefinition(IIndexMacro macro) { - try { - final char[] expansionImage = macro.getExpansionImage(); - if (expansionImage == null) { - // this is an undef - fMacroDictionary.remove(macro.getNameCharArray()); - } else { - PreprocessorMacro result= MacroDefinitionParser.parseMacroDefinition( - macro.getNameCharArray(), macro.getParameterList(), expansionImage); - fLocationMap.registerMacroFromIndex(result, macro.getDefinition(), -1); - fMacroDictionary.put(result.getNameCharArray(), result); - } - } catch (Exception e) { - fLog.traceLog("Invalid macro definition: '" + macro.getName() + "'"); //$NON-NLS-1$//$NON-NLS-2$ - } - } - - public ILocationResolver getLocationMap() { - return fLocationMap; - } + StringBuilder buffer = new StringBuilder("Scanner @ file:"); //$NON-NLS-1$ + buffer.append(fCurrentContext.toString()); + buffer.append(" line: "); //$NON-NLS-1$ + buffer.append(fLocationMap.getCurrentLineNumber(fCurrentContext.currentLexerToken().getOffset())); + return buffer.toString(); + } + + private void addMacroDefinition(IIndexMacro macro) { + try { + final char[] expansionImage = macro.getExpansionImage(); + if (expansionImage == null) { + // this is an undef + fMacroDictionary.remove(macro.getNameCharArray()); + } else { + PreprocessorMacro result = MacroDefinitionParser.parseMacroDefinition(macro.getNameCharArray(), + macro.getParameterList(), expansionImage); + fLocationMap.registerMacroFromIndex(result, macro.getDefinition(), -1); + fMacroDictionary.put(result.getNameCharArray(), result); + } + } catch (Exception e) { + fLog.traceLog("Invalid macro definition: '" + macro.getName() + "'"); //$NON-NLS-1$//$NON-NLS-2$ + } + } + + public ILocationResolver getLocationMap() { + return fLocationMap; + } @Override public void handleComment(boolean isBlockComment, int offset, int endOffset, AbstractCharArray input) { fLocationMap.encounteredComment(offset, endOffset, isBlockComment, input); } - @Override - public void handleProblem(int id, char[] arg, int offset, int endOffset) { - fLocationMap.encounterProblem(id, arg, offset, endOffset); - } - - /** - * Assumes that the pound token has not yet been consumed - * @since 5.0 - */ - private void executeDirective(final Lexer lexer, final int startOffset, boolean withinExpansion) - throws OffsetLimitReachedException { - final Token ident= lexer.nextToken(); - switch (ident.getType()) { - case IToken.tCOMPLETION: - lexer.nextToken(); - Token completionToken= new TokenWithImage(ident.getType(), null, - startOffset, ident.getEndOffset(), ("#" + ident.getImage()).toCharArray()); //$NON-NLS-1$ - throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, completionToken); - - case Lexer.tNEWLINE: - return; - - case IToken.tEND_OF_INPUT: - case IToken.tINTEGER: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - return; - - case IToken.tIDENTIFIER: - break; - - default: - int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, ident.getCharImage(), startOffset, endOffset); - return; - } - - // we have an identifier - final char[] name = ident.getCharImage(); - final int type = fPPKeywords.get(name); - int condEndOffset; - switch (type) { - case IPreprocessorDirective.ppImport: - case IPreprocessorDirective.ppInclude: - case IPreprocessorDirective.ppInclude_next: - executeInclude(lexer, startOffset, type, fCurrentContext.getCodeState() == CodeState.eActive, - withinExpansion); - break; - case IPreprocessorDirective.ppDefine: - CodeState state= fCurrentContext.getCodeState(); - if (state == CodeState.eSkipInactive) { - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - } else { - executeDefine(lexer, startOffset, state == CodeState.eActive); - } - break; - case IPreprocessorDirective.ppUndef: - state= fCurrentContext.getCodeState(); - if (state == CodeState.eSkipInactive) { - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - } else { - executeUndefine(lexer, startOffset, fCurrentContext.getCodeState() == CodeState.eActive); - } - break; - case IPreprocessorDirective.ppIfdef: - if (executeIfdef(lexer, startOffset, false, withinExpansion) == CodeState.eSkipInactive) - skipOverConditionalCode(lexer, withinExpansion); - break; - case IPreprocessorDirective.ppIfndef: - if (executeIfdef(lexer, startOffset, true, withinExpansion) == CodeState.eSkipInactive) - skipOverConditionalCode(lexer, withinExpansion); - break; - case IPreprocessorDirective.ppIf: - if (executeIf(lexer, startOffset, false, withinExpansion) == CodeState.eSkipInactive) - skipOverConditionalCode(lexer, withinExpansion); - break; - case IPreprocessorDirective.ppElif: - if (executeIf(lexer, startOffset, true, withinExpansion) == CodeState.eSkipInactive) { - skipOverConditionalCode(lexer, withinExpansion); - } - break; - case IPreprocessorDirective.ppElse: - if (executeElse(lexer, startOffset, withinExpansion) == CodeState.eSkipInactive) { - skipOverConditionalCode(lexer, withinExpansion); - } - break; - case IPreprocessorDirective.ppEndif: - executeEndif(lexer, startOffset, withinExpansion); - break; - case IPreprocessorDirective.ppWarning: - case IPreprocessorDirective.ppError: - int condOffset= lexer.nextToken().getOffset(); - condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - // Missing argument + @Override + public void handleProblem(int id, char[] arg, int offset, int endOffset) { + fLocationMap.encounterProblem(id, arg, offset, endOffset); + } + + /** + * Assumes that the pound token has not yet been consumed + * @since 5.0 + */ + private void executeDirective(final Lexer lexer, final int startOffset, boolean withinExpansion) + throws OffsetLimitReachedException { + final Token ident = lexer.nextToken(); + switch (ident.getType()) { + case IToken.tCOMPLETION: + lexer.nextToken(); + Token completionToken = new TokenWithImage(ident.getType(), null, startOffset, ident.getEndOffset(), + ("#" + ident.getImage()).toCharArray()); //$NON-NLS-1$ + throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, completionToken); + + case Lexer.tNEWLINE: + return; + + case IToken.tEND_OF_INPUT: + case IToken.tINTEGER: + lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + return; + + case IToken.tIDENTIFIER: + break; + + default: + int endOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, ident.getCharImage(), startOffset, endOffset); + return; + } + + // we have an identifier + final char[] name = ident.getCharImage(); + final int type = fPPKeywords.get(name); + int condEndOffset; + switch (type) { + case IPreprocessorDirective.ppImport: + case IPreprocessorDirective.ppInclude: + case IPreprocessorDirective.ppInclude_next: + executeInclude(lexer, startOffset, type, fCurrentContext.getCodeState() == CodeState.eActive, + withinExpansion); + break; + case IPreprocessorDirective.ppDefine: + CodeState state = fCurrentContext.getCodeState(); + if (state == CodeState.eSkipInactive) { + lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + } else { + executeDefine(lexer, startOffset, state == CodeState.eActive); + } + break; + case IPreprocessorDirective.ppUndef: + state = fCurrentContext.getCodeState(); + if (state == CodeState.eSkipInactive) { + lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + } else { + executeUndefine(lexer, startOffset, fCurrentContext.getCodeState() == CodeState.eActive); + } + break; + case IPreprocessorDirective.ppIfdef: + if (executeIfdef(lexer, startOffset, false, withinExpansion) == CodeState.eSkipInactive) + skipOverConditionalCode(lexer, withinExpansion); + break; + case IPreprocessorDirective.ppIfndef: + if (executeIfdef(lexer, startOffset, true, withinExpansion) == CodeState.eSkipInactive) + skipOverConditionalCode(lexer, withinExpansion); + break; + case IPreprocessorDirective.ppIf: + if (executeIf(lexer, startOffset, false, withinExpansion) == CodeState.eSkipInactive) + skipOverConditionalCode(lexer, withinExpansion); + break; + case IPreprocessorDirective.ppElif: + if (executeIf(lexer, startOffset, true, withinExpansion) == CodeState.eSkipInactive) { + skipOverConditionalCode(lexer, withinExpansion); + } + break; + case IPreprocessorDirective.ppElse: + if (executeElse(lexer, startOffset, withinExpansion) == CodeState.eSkipInactive) { + skipOverConditionalCode(lexer, withinExpansion); + } + break; + case IPreprocessorDirective.ppEndif: + executeEndif(lexer, startOffset, withinExpansion); + break; + case IPreprocessorDirective.ppWarning: + case IPreprocessorDirective.ppError: + int condOffset = lexer.nextToken().getOffset(); + condEndOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + // Missing argument if (condEndOffset < condOffset) { - condOffset= condEndOffset; + condOffset = condEndOffset; + } + if (fCurrentContext.getCodeState() == CodeState.eActive) { + int endOffset = lexer.currentToken().getEndOffset(); + final char[] warning = lexer.getInputChars(condOffset, condEndOffset); + final int id = type == IPreprocessorDirective.ppError ? IProblem.PREPROCESSOR_POUND_ERROR + : IProblem.PREPROCESSOR_POUND_WARNING; + handleProblem(id, warning, condOffset, condEndOffset); + fLocationMap.encounterPoundError(startOffset, condOffset, condEndOffset, endOffset); } - if (fCurrentContext.getCodeState() == CodeState.eActive) { - int endOffset= lexer.currentToken().getEndOffset(); - final char[] warning= lexer.getInputChars(condOffset, condEndOffset); - final int id= type == IPreprocessorDirective.ppError - ? IProblem.PREPROCESSOR_POUND_ERROR - : IProblem.PREPROCESSOR_POUND_WARNING; - handleProblem(id, warning, condOffset, condEndOffset); - fLocationMap.encounterPoundError(startOffset, condOffset, condEndOffset, endOffset); - } - break; - case IPreprocessorDirective.ppPragma: - Token pragmaToken= lexer.nextToken(); - condOffset= pragmaToken.getOffset(); - condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - // Missing argument + break; + case IPreprocessorDirective.ppPragma: + Token pragmaToken = lexer.nextToken(); + condOffset = pragmaToken.getOffset(); + condEndOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + // Missing argument if (condEndOffset < condOffset) { - condOffset= condEndOffset; + condOffset = condEndOffset; + } + if (fCurrentContext.getCodeState() == CodeState.eActive) { + int endOffset = lexer.currentToken().getEndOffset(); + fLocationMap.encounterPoundPragma(startOffset, condOffset, condEndOffset, endOffset); + if (CharArrayUtils.equals(ONCE, pragmaToken.getCharImage())) { + IFileNomination nom = fLocationMap.reportPragmaOnceSemantics(fCurrentContext.getLocationCtx()); + fFileContentProvider.reportPragmaOnceSemantics(getCurrentFilename(), nom); + } + } + break; + case IPreprocessorDirective.ppIgnore: + lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + break; + default: + int endOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + if (fCurrentContext.getCodeState() == CodeState.eActive) { + handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, ident.getCharImage(), startOffset, endOffset); } - if (fCurrentContext.getCodeState() == CodeState.eActive) { - int endOffset= lexer.currentToken().getEndOffset(); - fLocationMap.encounterPoundPragma(startOffset, condOffset, condEndOffset, endOffset); - if (CharArrayUtils.equals(ONCE, pragmaToken.getCharImage())) { - IFileNomination nom= fLocationMap.reportPragmaOnceSemantics(fCurrentContext.getLocationCtx()); - fFileContentProvider.reportPragmaOnceSemantics(getCurrentFilename(), nom); - } - } - break; - case IPreprocessorDirective.ppIgnore: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - break; - default: - int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - if (fCurrentContext.getCodeState() == CodeState.eActive) { - handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, ident.getCharImage(), - startOffset, endOffset); - } - break; - } - } - - private void executeInclude(final Lexer lexer, int poundOffset, int includeType, - boolean active, boolean withinExpansion) throws OffsetLimitReachedException { + break; + } + } + + private void executeInclude(final Lexer lexer, int poundOffset, int includeType, boolean active, + boolean withinExpansion) throws OffsetLimitReachedException { // Make sure to clear the extern include guard. - final char[] externGuard= fExternIncludeGuard; - fExternIncludeGuard= null; + final char[] externGuard = fExternIncludeGuard; + fExternIncludeGuard = null; if (withinExpansion) { - final char[] name= lexer.currentToken().getCharImage(); + final char[] name = lexer.currentToken().getCharImage(); final int endOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, name, poundOffset, endOffset); return; } - + lexer.setInsideIncludeDirective(true); - final Token header= lexer.nextToken(); + final Token header = lexer.nextToken(); lexer.setInsideIncludeDirective(false); - int condEndOffset= header.getEndOffset(); - final int[] nameOffsets= new int[] {header.getOffset(), condEndOffset}; - char[] headerName= null; - boolean userInclude= true; + int condEndOffset = header.getEndOffset(); + final int[] nameOffsets = new int[] { header.getOffset(), condEndOffset }; + char[] headerName = null; + boolean userInclude = true; switch (header.getType()) { case Lexer.tSYSTEM_HEADER_NAME: - userInclude= false; + userInclude = false; headerName = extractHeaderName(header.getCharImage(), '<', '>', nameOffsets); - condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + condEndOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); break; case Lexer.tQUOTE_HEADER_NAME: headerName = extractHeaderName(header.getCharImage(), '"', '"', nameOffsets); - condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + condEndOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); break; case IToken.tCOMPLETION: throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, header); case IToken.tIDENTIFIER: - TokenList tl= new TokenList(); - condEndOffset= nameOffsets[1]= getTokensWithinPPDirective(false, tl, false); - Token t= tl.first(); + TokenList tl = new TokenList(); + condEndOffset = nameOffsets[1] = getTokensWithinPPDirective(false, tl, false); + Token t = tl.first(); if (t != null) { switch (t.getType()) { case IToken.tSTRING: - headerName = extractHeaderName(t.getCharImage(), '"', '"', new int[]{0,0}); + headerName = extractHeaderName(t.getCharImage(), '"', '"', new int[] { 0, 0 }); break; case IToken.tLT: - userInclude= false; - boolean complete= false; - StringBuilder buf= new StringBuilder(); - t= (Token) t.getNext(); + userInclude = false; + boolean complete = false; + StringBuilder buf = new StringBuilder(); + t = (Token) t.getNext(); while (t != null) { if (t.getType() == IToken.tGT) { - complete= true; + complete = true; break; } buf.append(t.getImage()); - t= (Token) t.getNext(); + t = (Token) t.getNext(); } if (complete) { - headerName= new char[buf.length()]; + headerName = new char[buf.length()]; buf.getChars(0, buf.length(), headerName, 0); } } @@ -1554,18 +1652,18 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { break; default: - condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + condEndOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); break; } if (headerName == null || headerName.length == 0) { - if (active) { - handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, - lexer.getInputChars(poundOffset, condEndOffset), poundOffset, condEndOffset); - } + if (active) { + handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, lexer.getInputChars(poundOffset, condEndOffset), + poundOffset, condEndOffset); + } return; } - + if (includeType == IPreprocessorDirective.ppImport) { // Imports are executed only once. // See http://gcc.gnu.org/onlinedocs/gcc-3.2/cpp/Obsolete-once-only-headers.html. @@ -1578,10 +1676,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } } - if ((active && fCurrentContext.getDepth() == MAX_INCLUSION_DEPTH) || - (fPreventInclusion != null && fPreventInclusion.containsKey(headerName))) { + if ((active && fCurrentContext.getDepth() == MAX_INCLUSION_DEPTH) + || (fPreventInclusion != null && fPreventInclusion.containsKey(headerName))) { handleProblem(IProblem.PREPROCESSOR_EXCEEDS_MAXIMUM_INCLUSION_DEPTH, - lexer.getInputChars(poundOffset, condEndOffset), poundOffset, condEndOffset); + lexer.getInputChars(poundOffset, condEndOffset), poundOffset, condEndOffset); if (fPreventInclusion == null) fPreventInclusion = new CharArraySet(0); fPreventInclusion.put(headerName); @@ -1591,85 +1689,85 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { boolean includeNext = includeType == IPreprocessorDirective.ppInclude_next; final String includeDirective = new String(headerName); if (!active) { - // Inactive include - String path= null; - boolean isHeuristic= false; - IFileNomination nominationDelegate= null; - + // Inactive include + String path = null; + boolean isHeuristic = false; + IFileNomination nominationDelegate = null; + if (externGuard != null) { // #ifndef GUARD // #include "file.h" // #endif // When the extern guard matches we need to resolve the inclusion. We don't actually // check whether the guard matches. - final IncludeResolution resolved= findInclusion(includeDirective, userInclude, includeNext, + final IncludeResolution resolved = findInclusion(includeDirective, userInclude, includeNext, getCurrentFilename(), createPathTester); if (resolved != null) { nominationDelegate = fFileContentProvider.isIncludedWithPragmaOnceSemantics(resolved.fLocation); if (nominationDelegate != null) { - path= resolved.fLocation; - isHeuristic= resolved.fHeuristic; + path = resolved.fLocation; + isHeuristic = resolved.fHeuristic; } } } - fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1], - condEndOffset, headerName, path, userInclude, active, isHeuristic, nominationDelegate); + fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1], condEndOffset, headerName, + path, userInclude, active, isHeuristic, nominationDelegate); return; } - + // Active include - final InternalFileContent fi= findInclusion(includeDirective, userInclude, includeNext, - getCurrentFilename(), createCodeReaderTester); + final InternalFileContent fi = findInclusion(includeDirective, userInclude, includeNext, getCurrentFilename(), + createCodeReaderTester); if (fi == null) { // Unresolved active include final int len = headerName.length + 2; - StringBuilder name= new StringBuilder(len); + StringBuilder name = new StringBuilder(len); name.append(userInclude ? '"' : '<'); name.append(headerName); name.append(userInclude ? '"' : '>'); - final char[] nameChars= new char[len]; + final char[] nameChars = new char[len]; name.getChars(0, len, nameChars, 0); handleProblem(IProblem.PREPROCESSOR_INCLUSION_NOT_FOUND, nameChars, poundOffset, condEndOffset); - fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1], - condEndOffset, headerName, null, userInclude, active, false, null); + fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1], condEndOffset, headerName, + null, userInclude, active, false, null); return; } // Resolved active include - final String path= fi.getFileLocation(); - final boolean isHeuristic= fi.isFoundByHeuristics(); - final boolean pragmaOnceContext= fCurrentContext.isPragmaOnce(); + final String path = fi.getFileLocation(); + final boolean isHeuristic = fi.isFoundByHeuristics(); + final boolean pragmaOnceContext = fCurrentContext.isPragmaOnce(); - IFileNomination nominationDelegate= null; - ASTInclusionStatement stmt= null; + IFileNomination nominationDelegate = null; + ASTInclusionStatement stmt = null; List<ISignificantMacros> loadedVerisons = null; switch (fi.getKind()) { case FOUND_IN_INDEX: // Pulled in from index - nominationDelegate= fi.getFilesIncluded().get(0); + nominationDelegate = fi.getFilesIncluded().get(0); try { ISignificantMacros sm = nominationDelegate.getSignificantMacros(); fCurrentContext.addSignificantMacros(sm); - if (pragmaOnceContext && !nominationDelegate.hasPragmaOnceSemantics()) - loadedVerisons= fFileContentProvider.getLoadedVersions(path); + if (pragmaOnceContext && !nominationDelegate.hasPragmaOnceSemantics()) + loadedVerisons = fFileContentProvider.getLoadedVersions(path); } catch (CoreException e) { } - + processInclusionFromIndex(poundOffset, fi, true); break; case USE_SOURCE: // Will be parsed - AbstractCharArray source= fi.getSource(); + AbstractCharArray source = fi.getSource(); if (source != null) { - ILocationCtx ctx= fLocationMap.pushInclusion(poundOffset, nameOffsets[0], nameOffsets[1], + ILocationCtx ctx = fLocationMap.pushInclusion(poundOffset, nameOffsets[0], nameOffsets[1], condEndOffset, source, path, headerName, userInclude, isHeuristic, fi.isSource()); - ScannerContext fctx= new ScannerContext(ctx, fCurrentContext, + ScannerContext fctx = new ScannerContext(ctx, fCurrentContext, new Lexer(source, fLexOptions, this, this)); fctx.setFoundOnPath(fi.getFoundOnPath(), includeDirective); detectIncludeGuard(path, source, fctx); - fCurrentContext= fctx; - stmt= ctx.getInclusionStatement(); + fCurrentContext = fctx; + stmt = ctx.getInclusionStatement(); stmt.setIncludedFileTimestamp(fi.getTimestamp()); stmt.setIncludedFileSize(fi.getFileSize()); stmt.setIncludedFileContentsHash(source.getContentsHash()); @@ -1677,7 +1775,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { stmt.setErrorInIncludedFile(source.hasError()); if (!fCurrentContext.isPragmaOnce()) { // Track the loaded version count, even in a non-pragma-once context. - loadedVerisons= fFileContentProvider.getLoadedVersions(path); + loadedVerisons = fFileContentProvider.getLoadedVersions(path); fctx.setLoadedVersionCount(loadedVerisons.size()); } } @@ -1690,8 +1788,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } if (stmt == null) { // Found in index or skipped. - stmt= fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1], - condEndOffset, headerName, path, userInclude, active, isHeuristic, nominationDelegate); + stmt = fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1], condEndOffset, + headerName, path, userInclude, active, isHeuristic, nominationDelegate); } // In a pragma once context store loaded versions of this non-pragma-once include if (pragmaOnceContext && loadedVerisons != null && !loadedVerisons.isEmpty()) { @@ -1700,7 +1798,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } private void processInclusionFromIndex(int offset, InternalFileContent fi, boolean updateContext) { - List<IIndexMacro> mdefs= fi.getMacroDefinitions(); + List<IIndexMacro> mdefs = fi.getMacroDefinitions(); for (IIndexMacro macro : mdefs) { addMacroDefinition(macro); if (updateContext) @@ -1712,11 +1810,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { fLocationMap.skippedFile(fLocationMap.getSequenceNumberForOffset(offset), fi); } - private char[] extractHeaderName(final char[] image, final char startDelim, final char endDelim, - int[] offsets) { + private char[] extractHeaderName(final char[] image, final char startDelim, final char endDelim, int[] offsets) { char[] headerName; - int start= 0; - int length= image.length; + int start = 0; + int length = image.length; if (length > 0 && image[length - 1] == endDelim) { length--; offsets[1]--; @@ -1726,13 +1823,13 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { length--; } } - headerName= new char[length]; + headerName = new char[length]; System.arraycopy(image, start, headerName, 0, length); return headerName; } - - private void executeDefine(final Lexer lexer, int startOffset, boolean isActive) - throws OffsetLimitReachedException { + + private void executeDefine(final Lexer lexer, int startOffset, boolean isActive) + throws OffsetLimitReachedException { try { ObjectStyleMacro macrodef = fMacroDefinitionParser.parseMacroDefinition(lexer, this); if (isActive) { @@ -1740,127 +1837,126 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { fMacroDictionary.put(macroName, macrodef); fCurrentContext.internalModification(macroName); } - - final Token name= fMacroDefinitionParser.getNameToken(); + + final Token name = fMacroDefinitionParser.getNameToken(); fLocationMap.encounterPoundDefine(startOffset, name.getOffset(), name.getEndOffset(), macrodef.getExpansionOffset(), macrodef.getExpansionEndOffset(), isActive, macrodef); } catch (InvalidMacroDefinitionException e) { lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); handleProblem(IProblem.PREPROCESSOR_INVALID_MACRO_DEFN, e.fName, e.fStartOffset, e.fEndOffset); } - } - - private void executeUndefine(Lexer lexer, int startOffset, boolean isActive) - throws OffsetLimitReachedException { - final Token name= lexer.nextToken(); - final int tt= name.getType(); - if (tt != IToken.tIDENTIFIER) { - if (tt == IToken.tCOMPLETION) { - throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, name); - } - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - handleProblem(IProblem.PREPROCESSOR_INVALID_MACRO_DEFN, name.getCharImage(), startOffset, - name.getEndOffset()); - return; - } - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - final int endOffset= lexer.currentToken().getEndOffset(); - final char[] namechars= name.getCharImage(); - PreprocessorMacro definition; - if (isActive) { - definition= fMacroDictionary.remove(namechars, 0, namechars.length); - fCurrentContext.internalModification(namechars); - } else { - definition= fMacroDictionary.get(namechars); - } - fLocationMap.encounterPoundUndef(definition, startOffset, name.getOffset(), - name.getEndOffset(), endOffset, namechars, isActive); - } - - private CodeState executeIfdef(Lexer lexer, int offset, boolean isIfndef, - boolean withinExpansion) throws OffsetLimitReachedException { - final Token name= lexer.nextToken(); + } + + private void executeUndefine(Lexer lexer, int startOffset, boolean isActive) throws OffsetLimitReachedException { + final Token name = lexer.nextToken(); + final int tt = name.getType(); + if (tt != IToken.tIDENTIFIER) { + if (tt == IToken.tCOMPLETION) { + throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, name); + } + lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + handleProblem(IProblem.PREPROCESSOR_INVALID_MACRO_DEFN, name.getCharImage(), startOffset, + name.getEndOffset()); + return; + } + lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + final int endOffset = lexer.currentToken().getEndOffset(); + final char[] namechars = name.getCharImage(); + PreprocessorMacro definition; + if (isActive) { + definition = fMacroDictionary.remove(namechars, 0, namechars.length); + fCurrentContext.internalModification(namechars); + } else { + definition = fMacroDictionary.get(namechars); + } + fLocationMap.encounterPoundUndef(definition, startOffset, name.getOffset(), name.getEndOffset(), endOffset, + namechars, isActive); + } + + private CodeState executeIfdef(Lexer lexer, int offset, boolean isIfndef, boolean withinExpansion) + throws OffsetLimitReachedException { + final Token name = lexer.nextToken(); lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - final int tt= name.getType(); + final int tt = name.getType(); final int nameOffset = name.getOffset(); - final int nameEndOffset = name.getEndOffset(); - final int endOffset= lexer.currentToken().getEndOffset(); - - boolean isTaken= false; - PreprocessorMacro macro= null; - final Conditional conditional= fCurrentContext.newBranch(BranchKind.eIf, withinExpansion); + final int nameEndOffset = name.getEndOffset(); + final int endOffset = lexer.currentToken().getEndOffset(); + + boolean isTaken = false; + PreprocessorMacro macro = null; + final Conditional conditional = fCurrentContext.newBranch(BranchKind.eIf, withinExpansion); if (conditional.canHaveActiveBranch(withinExpansion)) { - // we need an identifier + // we need an identifier if (tt != IToken.tIDENTIFIER) { - if (tt == IToken.tCOMPLETION) { - throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, name); - } - // report problem and treat as inactive - handleProblem(IProblem.PREPROCESSOR_DEFINITION_NOT_FOUND, name.getCharImage(), offset, nameEndOffset); - } else { - final char[] namechars= name.getCharImage(); + if (tt == IToken.tCOMPLETION) { + throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, name); + } + // report problem and treat as inactive + handleProblem(IProblem.PREPROCESSOR_DEFINITION_NOT_FOUND, name.getCharImage(), offset, nameEndOffset); + } else { + final char[] namechars = name.getCharImage(); if (isIfndef) { - if (IncludeGuardDetection.detectIncludeEndif(lexer)) { - fExternIncludeGuard= namechars; - } - } - macro= fMacroDictionary.get(namechars); - isTaken= (macro == null) == isIfndef; - if (macro == null) { - macro = new UndefinedMacro(namechars); - fCurrentContext.significantMacroUndefined(namechars); - } else { - fCurrentContext.significantMacroDefined(namechars); - } - } - } - + if (IncludeGuardDetection.detectIncludeEndif(lexer)) { + fExternIncludeGuard = namechars; + } + } + macro = fMacroDictionary.get(namechars); + isTaken = (macro == null) == isIfndef; + if (macro == null) { + macro = new UndefinedMacro(namechars); + fCurrentContext.significantMacroUndefined(namechars); + } else { + fCurrentContext.significantMacroDefined(namechars); + } + } + } + ASTPreprocessorNode stmt; if (isIfndef) { - stmt= fLocationMap.encounterPoundIfndef(offset, nameOffset, nameEndOffset, endOffset, isTaken, macro); + stmt = fLocationMap.encounterPoundIfndef(offset, nameOffset, nameEndOffset, endOffset, isTaken, macro); } else { - stmt= fLocationMap.encounterPoundIfdef(offset, nameOffset, nameEndOffset, endOffset, isTaken, macro); + stmt = fLocationMap.encounterPoundIfdef(offset, nameOffset, nameEndOffset, endOffset, isTaken, macro); } if (!conditional.isActive(withinExpansion)) stmt.setInactive(); return fCurrentContext.setBranchState(conditional, isTaken, withinExpansion, offset); - } + } - private CodeState executeIf(Lexer lexer, int startOffset, boolean isElif, - boolean withinExpansion) throws OffsetLimitReachedException { - Conditional cond= fCurrentContext.newBranch(isElif ? BranchKind.eElif : BranchKind.eIf, withinExpansion); + private CodeState executeIf(Lexer lexer, int startOffset, boolean isElif, boolean withinExpansion) + throws OffsetLimitReachedException { + Conditional cond = fCurrentContext.newBranch(isElif ? BranchKind.eElif : BranchKind.eIf, withinExpansion); if (cond == null) { - char[] name= lexer.currentToken().getCharImage(); - int condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + char[] name = lexer.currentToken().getCharImage(); + int condEndOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, condEndOffset); return fCurrentContext.getCodeState(); } - - boolean isTaken= false; - IASTName[] refs= IASTName.EMPTY_NAME_ARRAY; - int condOffset= lexer.nextToken().getOffset(); + + boolean isTaken = false; + IASTName[] refs = IASTName.EMPTY_NAME_ARRAY; + int condOffset = lexer.nextToken().getOffset(); int condEndOffset, endOffset; if (cond.canHaveActiveBranch(withinExpansion)) { - char[] macro= IncludeGuardDetection.detectIfNotDefinedIncludeEndif(lexer); + char[] macro = IncludeGuardDetection.detectIfNotDefinedIncludeEndif(lexer); if (macro != null) { - fExternIncludeGuard= macro; - } + fExternIncludeGuard = macro; + } + + TokenList condition = new TokenList(); + condEndOffset = getTokensWithinPPDirective(true, condition, withinExpansion); + endOffset = lexer.currentToken().getEndOffset(); - TokenList condition= new TokenList(); - condEndOffset= getTokensWithinPPDirective(true, condition, withinExpansion); - endOffset= lexer.currentToken().getEndOffset(); - if (condition.first() == null) { handleProblem(IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, null, startOffset, endOffset); } else { try { fExpressionEvaluator.clearMacrosInDefinedExpression(); - isTaken= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap); + isTaken = fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap); refs = fExpressionEvaluator.clearMacrosInDefinedExpression(); for (IASTName iastName : refs) { - IBinding mb= iastName.getBinding(); + IBinding mb = iastName.getBinding(); if (mb instanceof UndefinedMacro) { fCurrentContext.significantMacroUndefined(iastName.toCharArray()); } else { @@ -1872,32 +1968,32 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } } } else { - condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); + condEndOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + endOffset = lexer.currentToken().getEndOffset(); } ASTPreprocessorNode stmt; if (isElif) { - stmt= fLocationMap.encounterPoundElif(startOffset, condOffset, condEndOffset, endOffset, isTaken, refs); + stmt = fLocationMap.encounterPoundElif(startOffset, condOffset, condEndOffset, endOffset, isTaken, refs); } else { - stmt= fLocationMap.encounterPoundIf(startOffset, condOffset, condEndOffset, endOffset, isTaken, refs); + stmt = fLocationMap.encounterPoundIf(startOffset, condOffset, condEndOffset, endOffset, isTaken, refs); } if (!cond.isActive(withinExpansion)) stmt.setInactive(); - + return fCurrentContext.setBranchState(cond, isTaken, withinExpansion, startOffset); - } + } - private CodeState executeElse(final Lexer lexer, final int startOffset,boolean withinExpansion) + private CodeState executeElse(final Lexer lexer, final int startOffset, boolean withinExpansion) throws OffsetLimitReachedException { - final int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - Conditional cond= fCurrentContext.newBranch(BranchKind.eElse, withinExpansion); + final int endOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + Conditional cond = fCurrentContext.newBranch(BranchKind.eElse, withinExpansion); if (cond == null) { handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, Keywords.cELSE, startOffset, endOffset); - return fCurrentContext.getCodeState(); + return fCurrentContext.getCodeState(); } - - final boolean isTaken= cond.canHaveActiveBranch(withinExpansion); + + final boolean isTaken = cond.canHaveActiveBranch(withinExpansion); ASTElse stmt = fLocationMap.encounterPoundElse(startOffset, endOffset, isTaken); if (!cond.isActive(withinExpansion)) stmt.setInactive(); @@ -1906,8 +2002,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { private CodeState executeEndif(Lexer lexer, int startOffset, boolean withinExpansion) throws OffsetLimitReachedException { - final int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - final Conditional cond= fCurrentContext.newBranch(BranchKind.eEnd, withinExpansion); + final int endOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + final Conditional cond = fCurrentContext.newBranch(BranchKind.eEnd, withinExpansion); if (cond == null) { handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, Keywords.cENDIF, startOffset, endOffset); } else { @@ -1917,61 +2013,60 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } return fCurrentContext.setBranchEndState(cond, withinExpansion, startOffset); } - - /** - * Runs the preprocessor on the rest of the line, storing the tokens in the holder supplied. - * Macro expansion is reported to the location map. - * In case isCondition is set to <code>true</code>, identifiers with image 'defined' are - * converted to the defined-token and its argument is not macro expanded. - * Returns the end-offset of the last token that was consumed. - */ - private int getTokensWithinPPDirective(boolean isCondition, TokenList result, - boolean withinExpansion) throws OffsetLimitReachedException { - final ScannerContext scannerCtx= fCurrentContext; - scannerCtx.clearInactiveCodeMarkerToken(); - int options= STOP_AT_NL | REPORT_SIGNIFICANT_MACROS; - if (isCondition) - options |= PROTECT_INTRINSICS; - - loop: while (true) { - Token t= internalFetchToken(scannerCtx, options, withinExpansion); - switch (t.getType()) { - case IToken.tEND_OF_INPUT: - case IToken.tCOMPLETION: - scannerCtx.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); // make sure the exception is thrown. - break loop; - case Lexer.tNEWLINE: - break loop; - case IToken.tIDENTIFIER: - break; - case tDEFINED: - options |= NO_EXPANSION; - break; - case t__HAS_FEATURE: - options |= NO_EXPANSION; - break; - case IToken.tLPAREN: - break; - default: - options &= ~NO_EXPANSION; - break; - } - result.append(t); - } - // make sure an exception is thrown if we are running content assist at the end of the line - return scannerCtx.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - } + + /** + * Runs the preprocessor on the rest of the line, storing the tokens in the holder supplied. + * Macro expansion is reported to the location map. + * In case isCondition is set to <code>true</code>, identifiers with image 'defined' are + * converted to the defined-token and its argument is not macro expanded. + * Returns the end-offset of the last token that was consumed. + */ + private int getTokensWithinPPDirective(boolean isCondition, TokenList result, boolean withinExpansion) + throws OffsetLimitReachedException { + final ScannerContext scannerCtx = fCurrentContext; + scannerCtx.clearInactiveCodeMarkerToken(); + int options = STOP_AT_NL | REPORT_SIGNIFICANT_MACROS; + if (isCondition) + options |= PROTECT_INTRINSICS; + + loop: while (true) { + Token t = internalFetchToken(scannerCtx, options, withinExpansion); + switch (t.getType()) { + case IToken.tEND_OF_INPUT: + case IToken.tCOMPLETION: + scannerCtx.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); // make sure the exception is thrown. + break loop; + case Lexer.tNEWLINE: + break loop; + case IToken.tIDENTIFIER: + break; + case tDEFINED: + options |= NO_EXPANSION; + break; + case t__HAS_FEATURE: + options |= NO_EXPANSION; + break; + case IToken.tLPAREN: + break; + default: + options &= ~NO_EXPANSION; + break; + } + result.append(t); + } + // make sure an exception is thrown if we are running content assist at the end of the line + return scannerCtx.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + } private void skipOverConditionalCode(final Lexer lexer, boolean withinExpansion) throws OffsetLimitReachedException { - CodeState state= CodeState.eSkipInactive; + CodeState state = CodeState.eSkipInactive; while (state == CodeState.eSkipInactive) { - state= skipBranch(lexer, withinExpansion); + state = skipBranch(lexer, withinExpansion); } } - private CodeState skipBranch(final Lexer lexer, boolean withinExpansion) - throws OffsetLimitReachedException { + private CodeState skipBranch(final Lexer lexer, boolean withinExpansion) throws OffsetLimitReachedException { while (true) { final Token pound = lexer.nextDirective(); int tt = pound.getType(); @@ -2035,10 +2130,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { * @param isPPCondition whether the expansion is inside of a preprocessor condition. This * implies a specific handling for the defined token. */ - private boolean expandMacro(final Token identifier, Lexer lexer, int options, - boolean withinExpansion) throws OffsetLimitReachedException { + private boolean expandMacro(final Token identifier, Lexer lexer, int options, boolean withinExpansion) + throws OffsetLimitReachedException { final boolean reportSignificant = (options & REPORT_SIGNIFICANT_MACROS) != 0; - final char[] name= identifier.getCharImage(); + final char[] name = identifier.getCharImage(); if ((options & PROTECT_INTRINSICS) != 0) { if (CharArrayUtils.equals(name, Keywords.cDEFINED)) { identifier.setType(tDEFINED); @@ -2049,40 +2144,40 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return false; } } - PreprocessorMacro macro= fMacroDictionary.get(name); - if (macro == null) { - if (reportSignificant && (options & IGNORE_UNDEFINED_SIGNIFICANT_MACROS) == 0) - fCurrentContext.significantMacroUndefined(name); - return false; - } - boolean stopAtNewline= (options & STOP_AT_NL) != 0; - if (macro instanceof FunctionStyleMacro) { - Token t= lexer.currentToken(); - if (!stopAtNewline) { - while (t.getType() == Lexer.tNEWLINE) { - t= lexer.nextToken(); - } - } - if (t.getType() != IToken.tLPAREN) { - if (reportSignificant) - fCurrentContext.significantMacro(macro); - return false; - } - } - final boolean contentAssist = fContentAssistLimit >= 0 && fCurrentContext == fRootContext; - final ITokenSequence input= stopAtNewline ? fLineInputToMacroExpansion : fInputToMacroExpansion; - final MacroExpander expander = withinExpansion ? - new MacroExpander(this, fMacroDictionary, fLocationMap, fLexOptions) : fMacroExpander; - TokenList replacement= expander.expand(input, options, macro, identifier, contentAssist, fCurrentContext); - final IASTName[] expansions= expander.clearImplicitExpansions(); - final ImageLocationInfo[] ili= expander.clearImageLocationInfos(); - final Token last= replacement.last(); - final int length= last == null ? 0 : last.getEndOffset(); - ILocationCtx ctx= fLocationMap.pushMacroExpansion( - identifier.getOffset(), identifier.getEndOffset(), lexer.getLastEndOffset(), length, - macro, expansions, ili); - fCurrentContext= new ScannerContext(ctx, fCurrentContext, replacement); - return true; + PreprocessorMacro macro = fMacroDictionary.get(name); + if (macro == null) { + if (reportSignificant && (options & IGNORE_UNDEFINED_SIGNIFICANT_MACROS) == 0) + fCurrentContext.significantMacroUndefined(name); + return false; + } + boolean stopAtNewline = (options & STOP_AT_NL) != 0; + if (macro instanceof FunctionStyleMacro) { + Token t = lexer.currentToken(); + if (!stopAtNewline) { + while (t.getType() == Lexer.tNEWLINE) { + t = lexer.nextToken(); + } + } + if (t.getType() != IToken.tLPAREN) { + if (reportSignificant) + fCurrentContext.significantMacro(macro); + return false; + } + } + final boolean contentAssist = fContentAssistLimit >= 0 && fCurrentContext == fRootContext; + final ITokenSequence input = stopAtNewline ? fLineInputToMacroExpansion : fInputToMacroExpansion; + final MacroExpander expander = withinExpansion + ? new MacroExpander(this, fMacroDictionary, fLocationMap, fLexOptions) + : fMacroExpander; + TokenList replacement = expander.expand(input, options, macro, identifier, contentAssist, fCurrentContext); + final IASTName[] expansions = expander.clearImplicitExpansions(); + final ImageLocationInfo[] ili = expander.clearImageLocationInfos(); + final Token last = replacement.last(); + final int length = last == null ? 0 : last.getEndOffset(); + ILocationCtx ctx = fLocationMap.pushMacroExpansion(identifier.getOffset(), identifier.getEndOffset(), + lexer.getLastEndOffset(), length, macro, expansions, ili); + fCurrentContext = new ScannerContext(ctx, fCurrentContext, replacement); + return true; } /** @@ -2119,20 +2214,20 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { */ public static boolean isPreprocessorProvidedMacro(char[] name) { return CharArrayUtils.equals(__LINE__.getNameCharArray(), name) - || CharArrayUtils.equals(__FILE__.getNameCharArray(), name) - || CharArrayUtils.equals(__DATE__.getNameCharArray(), name) - || CharArrayUtils.equals(__TIME__.getNameCharArray(), name); + || CharArrayUtils.equals(__FILE__.getNameCharArray(), name) + || CharArrayUtils.equals(__DATE__.getNameCharArray(), name) + || CharArrayUtils.equals(__TIME__.getNameCharArray(), name); } - + @SuppressWarnings("nls") public Set<String> getSupportedFeatures() { if (sSupportedFeatures == null) { sSupportedFeatures = new HashSet<>(); - + // C++98 features sSupportedFeatures.add("cxx_exceptions"); sSupportedFeatures.add("cxx_rtti"); - + // C++11 features // missing: cxx_access_control_sfinae (needs to be tested) sSupportedFeatures.add("cxx_alias_templates"); @@ -2171,7 +2266,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { // missing: cxx_unrestricted_unions (bug 327299) sSupportedFeatures.add("cxx_user_literals"); sSupportedFeatures.add("cxx_variadic_templates"); - + // C++14 features // missing: cxx_aggregate_nsdmi // missing: cxx_binary_literals @@ -2182,7 +2277,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { sSupportedFeatures.add("cxx_relaxed_constexpr"); // missing: cxx_return_type_deduction (bug 408470) sSupportedFeatures.add("cxx_variable_templates"); - + // C11 features sSupportedFeatures.add("c_alignas"); sSupportedFeatures.add("c_alignof"); @@ -2190,12 +2285,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { // missing: c_generic_selections (bug 445296) // missing: c_static_assert (bug 445297) // missing: c_thread_local (bug 445297) - + // Type trait primitives // Whether support for these is activated depends on the scanner extension // configuration, so check it and report support accordingly. // Note also that having a keyword for it doesn't necessarily mean we fully - // support it. For example, currently we have a keyword + // support it. For example, currently we have a keyword // GCCKeywords.cp__has_nothrown_assign, but we don't support evaluation of // this trait at the semantics level, so we don't report support for it. // missing: has_nothrow_assign @@ -2232,7 +2327,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } return sSupportedFeatures; } - + private void addTypeTraitPrimitive(String featureName, char[] keyword) { if (fKeywords.containsKey(keyword)) { sSupportedFeatures.add(featureName); |