/** * Copyright 2012 Tobias Gierke <tobias.gierke@code-sourcery.de> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.codesourcery.jasm16.ast; import java.io.IOException; import org.apache.log4j.Logger; import de.codesourcery.jasm16.compiler.CompilationError; import de.codesourcery.jasm16.compiler.ICompilationUnit; import de.codesourcery.jasm16.compiler.io.IResource; import de.codesourcery.jasm16.compiler.io.IResource.ResourceType; import de.codesourcery.jasm16.exceptions.ParseException; import de.codesourcery.jasm16.exceptions.ResourceNotFoundException; import de.codesourcery.jasm16.lexer.TokenType; import de.codesourcery.jasm16.parser.IParseContext; import de.codesourcery.jasm16.parser.IParser.ParserOption; import de.codesourcery.jasm16.utils.ITextRegion; import de.codesourcery.jasm16.utils.TextRegion; /** * The '.include' AST node. * * @author tobias.gierke@code-sourcery.de */ public class IncludeSourceFileNode extends ASTNode { private static final Logger LOG = Logger .getLogger(IncludeSourceFileNode.class); private String resourceIdentifier; private IResource resource; @Override protected ASTNode copySingleNode() { final IncludeSourceFileNode result = new IncludeSourceFileNode(); result.resource = resource; result.resourceIdentifier = resourceIdentifier; return result; } @Override public ASTNode createCopy(boolean shallow) { return super.createCopy(true); } public IResource getResource() { return resource; } @Override protected ASTNode parseInternal(IParseContext context) throws ParseException { final ITextRegion region = new TextRegion( context.read( TokenType.INCLUDE_SOURCE ) ); if ( context.peek().isWhitespace() ) { region.merge( context.read( TokenType.WHITESPACE ) ); } final String path = context.parseString( region ); this.resourceIdentifier = path; mergeWithAllTokensTextRegion( region ); try { resource = context.resolveRelative( path , context.getCompilationUnit().getResource() ); } catch (ResourceNotFoundException e) { context.getCompilationUnit().addMarker( new CompilationError("File '"+path+"' does not exist",context.getCompilationUnit() , region ) ); } if ( ! context.hasParserOption( ParserOption.NO_SOURCE_INCLUDE_PROCESSING ) ) { try { if ( resource.getType() == ResourceType.SOURCE_CODE ) { final ICompilationUnit existing = context.getCompilationUnitFor( resource ); AST ast = existing != null ? existing.getAST() : null; if ( ast == null ) { final IParseContext subContext = context.createParseContextForInclude( resource ); ast = (AST) new AST().parse( subContext ); subContext.getCompilationUnit().setAST( ast ); } if ( ! context.isParsingMacroDefinition() ) // TODO: I currently don't allow this for complexity reasons (clashes arg names <-> global defines etc.) { addChild( ast , context , false ); } else { context.getCompilationUnit().addMarker( new CompilationError("Including source files inside macro definitions is not allowed",context.getCompilationUnit() , region ) ); } } else { context.getCompilationUnit().addMarker( new CompilationError("Including file "+resource.getIdentifier()+" that is not recognized as a source file is not supported - please configure your project appropriately", context.getCompilationUnit() , region ) ); } } catch (IOException e) { LOG.error("parseInternal(): I/O error while including '"+path+"' : ",e); context.getCompilationUnit().addMarker( new CompilationError("I/O error while including '"+path+"' : "+e.getMessage(), context.getCompilationUnit() , region ) ); } } return this; } @Override public boolean supportsChildNodes() { return true; } public String getResourceIdentifier() { return resourceIdentifier; } }