package buntatsun.cdt.proc; import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration; import org.eclipse.cdt.core.parser.FileContent; import org.eclipse.cdt.core.parser.IParserLogService; import org.eclipse.cdt.core.parser.IProblem; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.IncludeFileContentProvider; import org.eclipse.cdt.core.parser.OffsetLimitReachedException; import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.util.CharArrayIntMap; import org.eclipse.cdt.core.parser.util.CharArrayMap; import org.eclipse.cdt.internal.core.parser.scanner.ASTInclusionStatement; import org.eclipse.cdt.internal.core.parser.scanner.AbstractCharArray; import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor; import org.eclipse.cdt.internal.core.parser.scanner.ILexerLog; import org.eclipse.cdt.internal.core.parser.scanner.ILocationCtx; import org.eclipse.cdt.internal.core.parser.scanner.Lexer; import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions; import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext; import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.CodeState; import org.eclipse.cdt.internal.core.parser.scanner.Token; @SuppressWarnings("restriction") public class ProCPreprocessor extends CPreprocessor { public ProCPreprocessor(FileContent fileContent, IScannerInfo info, ParserLanguage language, IParserLogService log, IScannerExtensionConfiguration configuration, IncludeFileContentProvider readerFactory) { super(fileContent, info, language, log, configuration, readerFactory); addProCHeaderReplaces(); addProCKeywords(); } private CharArrayIntMap fProCKeywords = new CharArrayIntMap(10, -1); protected void addProCKeywords() { fProCKeywords.put(ProCKeywords.cp_EXEC, IProCToken.tEXEC); fProCKeywords.put(ProCKeywords.cp_exec, IProCToken.tEXEC); fProCKeywords.put(ProCKeywords.cp_SQL, IProCToken.tSQL); fProCKeywords.put(ProCKeywords.cp_sql, IProCToken.tSQL); fProCKeywords.put(ProCKeywords.cp_ORACLE, IProCToken.tORACLE); fProCKeywords.put(ProCKeywords.cp_oracle, IProCToken.tORACLE); fProCKeywords.put(ProCKeywords.cp_TOOLS , IProCToken.tTOOLS); fProCKeywords.put(ProCKeywords.cp_tools , IProCToken.tTOOLS); fProCKeywords.put(ProCKeywords.cp_IAF , IProCToken.tIAF); fProCKeywords.put(ProCKeywords.cp_iaf , IProCToken.tIAF); fProCKeywords.put(ProCKeywords.cp_INCLUDE , IProCToken.tINCLUDE); fProCKeywords.put(ProCKeywords.cp_include , IProCToken.tINCLUDE); fProCKeywords.put(ProCKeywords.cp_EXECUTE , IProCToken.tEXECUTE); fProCKeywords.put(ProCKeywords.cp_execute , IProCToken.tEXECUTE); fProCKeywords.put(ProCKeywords.cp_DECLARE, IProCToken.tDECLARE); fProCKeywords.put(ProCKeywords.cp_declare, IProCToken.tDECLARE); fProCKeywords.put(ProCKeywords.cp_BEGIN, IProCToken.tBEGIN); fProCKeywords.put(ProCKeywords.cp_begin, IProCToken.tBEGIN); fProCKeywords.put(ProCKeywords.cp_END_EXEC , IProCToken.tEND_EXEC); fProCKeywords.put(ProCKeywords.cp_end_exec , IProCToken.tEND_EXEC); } private CharArrayMap<char[]> fHeaderReplaces = new CharArrayMap<>(8); protected void addProCHeaderReplaces() { fHeaderReplaces.put(ProCKeywords.rh_ORACA_H, ProCKeywords.rh_oraca_h); fHeaderReplaces.put(ProCKeywords.rh_SQLCA_H, ProCKeywords.rh_sqlca_h); fHeaderReplaces.put(ProCKeywords.rh_SQLDA_H, ProCKeywords.rh_sqlda_h); fHeaderReplaces.put(ProCKeywords.rh_ORACA, ProCKeywords.rh_oraca_h); fHeaderReplaces.put(ProCKeywords.rh_SQLCA, ProCKeywords.rh_sqlca_h); fHeaderReplaces.put(ProCKeywords.rh_SQLDA, ProCKeywords.rh_sqlda_h); fHeaderReplaces.put(ProCKeywords.rh_oraca, ProCKeywords.rh_oraca_h); fHeaderReplaces.put(ProCKeywords.rh_sqlca, ProCKeywords.rh_sqlca_h); fHeaderReplaces.put(ProCKeywords.rh_sqlda, ProCKeywords.rh_sqlda_h); } int previousToken = 0; boolean isInsideProCBlock = false; int endOfProCBlock = IToken.tSEMI; @Override protected Token internalFetchToken(ScannerContext uptoEndOfCtx, int options, boolean withinExpansion) throws OffsetLimitReachedException { Token ppToken= fCurrentContext.currentLexerToken(); while (true) { if (isInsideProCBlock && previousToken != IToken.tCOLON) { /* * Pro*C */ final int ppt = fProCKeywords.get(ppToken.getCharImage()); if (ppt > 0) { ppToken.setType(ppt); } } final int type = ppToken.getType(); switch (type) { 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); } } previousToken = ppToken.getType(); 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 IProCToken.tEXEC: /* * Pro*C */ Token tokenExec = ppToken; // save "EXEC" // skip newlines while ((ppToken = fCurrentContext.nextPPToken()).getType() == Lexer.tNEWLINE) { ; } tokenExec.setNext(ppToken); final int ppt = fProCKeywords.get(ppToken.getCharImage()); switch (ppt) { case IProCToken.tSQL: case IProCToken.tORACLE: case IProCToken.tTOOLS: case IProCToken.tIAF: isInsideProCBlock = true; endOfProCBlock = IToken.tSEMI; final ProCLexer pl = (ProCLexer) fCurrentContext.getLexer(); if (pl != null) { pl.saveState(); pl.isInsideProCBlock = true; } ppToken = fCurrentContext.nextPPToken(); final char[] ppName = ppToken.getCharImage(); final int ppType = fProCKeywords.get(ppName); switch (ppType) { case IProCToken.tINCLUDE: isInsideProCBlock = false; final Lexer lexer= fCurrentContext.getLexer(); if (lexer != null) { executeInclude(lexer, ppToken.getOffset(), ppType, fCurrentContext.getCodeState() == CodeState.eActive, withinExpansion); ppToken= fCurrentContext.currentLexerToken(); if (pl != null) { pl.isInsideProCBlock = false; } continue; } break; } if (pl != null) { pl.restoreState(); } break; default: tokenExec.setType(IToken.tIDENTIFIER); ppToken = tokenExec; } previousToken = tokenExec.getType(); return tokenExec; // return "EXEC" case IProCToken.tEXECUTE: final Token tokenExecute = ppToken; // save "EXECUTE" // skip newlines while ((ppToken = fCurrentContext.nextPPToken()).getType() == Lexer.tNEWLINE) { ; } final char[] ppName = ppToken.getCharImage(); final int ppType = fProCKeywords.get(ppName); switch (ppType) { case IProCToken.tDECLARE: case IProCToken.tBEGIN: endOfProCBlock = IProCToken.tEND_EXEC; break; } previousToken = tokenExecute.getType(); return tokenExecute; } if (isInsideProCBlock) { /* * Pro*C */ if (type == endOfProCBlock) { isInsideProCBlock = false; endOfProCBlock = IToken.tSEMI; final ProCLexer pl = (ProCLexer) fCurrentContext.getLexer(); if (pl != null) { pl.isInsideProCBlock = false; } } } fCurrentContext.nextPPToken(); previousToken = ppToken.getType(); return ppToken; } } @Override protected boolean expandMacro(final Token identifier, Lexer lexer, int options, boolean withinExpansion) throws OffsetLimitReachedException { if (isInsideProCBlock) { /* * Inside Pro*C Block, not expand macro */ return false; } return super.expandMacro(identifier, lexer, options, withinExpansion); } @Override protected char[] extractHeaderName( final char[] image, final char startDelim, final char endDelim, int[] offsets) { char[] headerName = super.extractHeaderName(image, startDelim, endDelim, offsets); char[] headerNameConv = null; headerNameConv = fHeaderReplaces.get(headerName); return headerNameConv == null ? headerName : headerNameConv; } @Override protected Lexer newLexer(char[] input, LexerOptions options, ILexerLog log, Object source) { return new ProCLexer(input, options, log, source); } @Override protected Lexer newLexer(AbstractCharArray input, LexerOptions options, ILexerLog log, Object source) { return new ProCLexer(input, options, log, source); } }