mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Fix for 205567: Implement an assembly model builder
This commit is contained in:
parent
587bbaf41a
commit
57d7ac7888
10 changed files with 733 additions and 4 deletions
|
@ -51,6 +51,7 @@ public class AllCoreTests {
|
|||
//which includes the CConfigurationDescriptionReferenceTests
|
||||
suite.addTest(AllCProjectDescriptionTests.suite());
|
||||
suite.addTest(ASTCacheTests.suite());
|
||||
suite.addTest(AsmModelBuilderTest.suite());
|
||||
return suite;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Anton Leherbauer (Wind River Systems) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.model.tests;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.eclipse.cdt.core.dom.IPDOMManager;
|
||||
import org.eclipse.cdt.core.model.IAsmLabel;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.IParent;
|
||||
import org.eclipse.cdt.core.model.ISourceRange;
|
||||
import org.eclipse.cdt.core.model.ISourceReference;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
||||
import org.eclipse.cdt.core.testplugin.CTestPlugin;
|
||||
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
||||
|
||||
/**
|
||||
* Tests for the default assembly model builder.
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public class AsmModelBuilderTest extends BaseTestCase {
|
||||
|
||||
public static Test suite() {
|
||||
return suite(AsmModelBuilderTest.class, "_");
|
||||
}
|
||||
|
||||
private ICProject fCProject;
|
||||
private ITranslationUnit fTU;
|
||||
|
||||
public AsmModelBuilderTest(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
fCProject= CProjectHelper.createCProject(getName(), null, IPDOMManager.ID_FAST_INDEXER);
|
||||
assertNotNull(fCProject);
|
||||
CProjectHelper.importSourcesFromPlugin(fCProject, CTestPlugin.getDefault().getBundle(), "/resources/asmTests");
|
||||
fTU= (ITranslationUnit) CProjectHelper.findElement(fCProject, "AsmTest.S");
|
||||
assertNotNull(fTU);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
CProjectHelper.delete(fCProject);
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testAsmModelElements() throws Exception {
|
||||
ICElement[] children= fTU.getChildren();
|
||||
assertEquals(7, children.length);
|
||||
|
||||
assertEquals(ICElement.C_INCLUDE, children[0].getElementType());
|
||||
assertEquals("include.h", children[0].getElementName());
|
||||
|
||||
assertEquals(ICElement.ASM_LABEL, children[1].getElementType());
|
||||
assertEquals("nonGlobalLabel", children[1].getElementName());
|
||||
assertFalse(((IAsmLabel)children[1]).isGlobal());
|
||||
assertEquals(0, ((IParent)children[1]).getChildren().length);
|
||||
|
||||
assertEquals(ICElement.ASM_LABEL, children[2].getElementType());
|
||||
assertEquals("globalLabel1", children[2].getElementName());
|
||||
assertTrue(((IAsmLabel)children[2]).isGlobal());
|
||||
assertEquals(2, ((IParent)children[2]).getChildren().length);
|
||||
|
||||
assertEquals(ICElement.C_MACRO, children[3].getElementType());
|
||||
assertEquals("MACRO", children[3].getElementName());
|
||||
|
||||
assertEquals(ICElement.ASM_LABEL, children[4].getElementType());
|
||||
assertEquals("globalLabel2", children[4].getElementName());
|
||||
assertTrue(((IAsmLabel)children[4]).isGlobal());
|
||||
assertEquals(1, ((IParent)children[4]).getChildren().length);
|
||||
|
||||
assertEquals(ICElement.ASM_LABEL, children[5].getElementType());
|
||||
assertEquals("globalLabel3", children[5].getElementName());
|
||||
assertTrue(((IAsmLabel)children[5]).isGlobal());
|
||||
assertEquals(1, ((IParent)children[5]).getChildren().length);
|
||||
|
||||
assertEquals(ICElement.ASM_LABEL, children[6].getElementType());
|
||||
assertEquals("alloca", children[6].getElementName());
|
||||
assertTrue(((IAsmLabel)children[6]).isGlobal());
|
||||
assertEquals(0, ((IParent)children[6]).getChildren().length);
|
||||
}
|
||||
|
||||
public void testAsmLabelRanges() throws Exception {
|
||||
String source= fTU.getBuffer().getContents();
|
||||
ICElement[] labels= (ICElement[]) fTU.getChildrenOfType(ICElement.ASM_LABEL).toArray(new ICElement[0]);
|
||||
for (int i = 0; i < labels.length; i++) {
|
||||
String name= labels[i].getElementName();
|
||||
ISourceReference label= (ISourceReference)labels[i];
|
||||
ISourceRange range= label.getSourceRange();
|
||||
assertEquals(source.substring(range.getIdStartPos(), range.getIdStartPos() + range.getIdLength()), name);
|
||||
int endOfLabel= source.indexOf("/* end */", range.getIdStartPos());
|
||||
assertEquals(range.getIdStartPos(), range.getStartPos());
|
||||
assertEquals(endOfLabel, range.getStartPos() + range.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
63
core/org.eclipse.cdt.core.tests/resources/asmTests/AsmTest.S
Normal file
63
core/org.eclipse.cdt.core.tests/resources/asmTests/AsmTest.S
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* AsmTest.S
|
||||
*/
|
||||
|
||||
#include <include.h>
|
||||
|
||||
.globl globalLabel1
|
||||
.global globalLabel2, globalLabel3
|
||||
|
||||
nonGlobalLabel:
|
||||
nop
|
||||
ret @ arm style comment
|
||||
/* end */
|
||||
|
||||
globalLabel1:
|
||||
movl %esp, %eax
|
||||
movl %eax, storage
|
||||
otherLabel1:
|
||||
movb $0x81, %ah # end-of-line comment
|
||||
jmp globalLabel2
|
||||
|
||||
; data
|
||||
storage:
|
||||
.long 0
|
||||
/* end */
|
||||
|
||||
#define MACRO mmm
|
||||
|
||||
/*
|
||||
* block comment
|
||||
*/
|
||||
globalLabel2:
|
||||
movl %esp, %eax
|
||||
movl %eax, storage
|
||||
|
||||
; line comment
|
||||
|
||||
otherLabel2:
|
||||
movb $0x81, %ah ; end-of-line comment
|
||||
jmp globalLabel3 # comment
|
||||
/* end */
|
||||
|
||||
globalLabel3:
|
||||
movl %esp, %eax
|
||||
movl %eax, storage
|
||||
|
||||
otherLabel3:
|
||||
movb $0x81, %ah
|
||||
jmp globalLabel3
|
||||
/* end */
|
||||
|
||||
.global alloca
|
||||
alloca:
|
||||
popl %edx
|
||||
popl %eax
|
||||
addl $3,%eax
|
||||
andl $0xfffffffc,%eax
|
||||
subl %eax,%esp
|
||||
movl %esp,%eax
|
||||
pushl %eax
|
||||
pushl %edx
|
||||
ret
|
||||
/* end */
|
|
@ -0,0 +1,28 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Anton Leherbauer (Wind River Systems) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.model;
|
||||
|
||||
/**
|
||||
* Represents a label in assembly code.
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface IAsmLabel extends ICElement, ISourceManipulation, ISourceReference {
|
||||
|
||||
/**
|
||||
* Test whether this label is declared global.
|
||||
* A global label is available to the linker.
|
||||
*
|
||||
* @return <code>true</code> if the label is global
|
||||
*/
|
||||
boolean isGlobal();
|
||||
|
||||
}
|
|
@ -226,6 +226,13 @@ public interface ICElement extends IAdaptable {
|
|||
*/
|
||||
static final int C_UNKNOWN_DECLARATION = 93;
|
||||
|
||||
/**
|
||||
* Assembly label.
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
static final int ASM_LABEL= 94;
|
||||
|
||||
/**
|
||||
* Modifier indicating a class constructor
|
||||
* @deprecated use {@link IMethodDeclaration#isConstructor()}
|
||||
|
@ -246,6 +253,7 @@ public interface ICElement extends IAdaptable {
|
|||
|
||||
/**
|
||||
* Modifier indicating an extern storage attribute
|
||||
* @deprecated not used anymore
|
||||
*/
|
||||
static final int C_STORAGE_EXTERN = 0x800;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2006 IBM Corporation and others.
|
||||
* Copyright (c) 2005, 2007 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -7,9 +7,11 @@
|
|||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
* Anton Leherbauer (Wind River Systems)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.model;
|
||||
|
||||
|
||||
/**
|
||||
* Interface supported by model builders for contributed languages.
|
||||
*
|
||||
|
@ -25,6 +27,22 @@ package org.eclipse.cdt.core.model;
|
|||
* @author Jeff Overbey
|
||||
*/
|
||||
public interface IContributedModelBuilder {
|
||||
|
||||
/**
|
||||
* A factory to create a model builder for a translation unit.
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface Factory {
|
||||
/**
|
||||
* Create a model builder for the given translation unit.
|
||||
*
|
||||
* @param tu the translation unit
|
||||
* @return the model builder or <code>null</code> if no model builder could be created
|
||||
*/
|
||||
IContributedModelBuilder create(ITranslationUnit tu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used when a <code>TranslationUnit</code> needs to be parsed.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Anton Leherbauer (Wind River Systems) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.model;
|
||||
|
||||
import org.eclipse.cdt.core.model.IAsmLabel;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.IParent;
|
||||
|
||||
/**
|
||||
* A label in assembly code.
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public class AsmLabel extends SourceManipulation implements IAsmLabel, IParent {
|
||||
|
||||
private final int fIndex;
|
||||
private final boolean fIsGlobal;
|
||||
|
||||
/**
|
||||
* Create a new assembly label.
|
||||
*
|
||||
* @param parent the parent element (must be ITranslationUnit)
|
||||
* @param name the name of the label
|
||||
* @param global if <code>true</code>, the label is declared global (visible to the linker)
|
||||
* @param index numbering of labels with the same name
|
||||
*/
|
||||
public AsmLabel(ICElement parent, String name, boolean global, int index) {
|
||||
super(parent, name, ICElement.ASM_LABEL);
|
||||
fIsGlobal= global;
|
||||
fIndex= index;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see org.eclipse.cdt.core.model.IAsmLabel#isGlobal()
|
||||
*/
|
||||
public final boolean isGlobal() {
|
||||
return fIsGlobal;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see org.eclipse.cdt.internal.core.model.CElement#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof AsmLabel) {
|
||||
return equals(this, (AsmLabel) o);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean equals(AsmLabel lhs, AsmLabel rhs) {
|
||||
if (CElement.equals(lhs, rhs)) {
|
||||
return lhs.fIndex == rhs.fIndex && lhs.fIsGlobal == rhs.fIsGlobal;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,414 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Anton Leherbauer (Wind River Systems) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.core.model;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.IContributedModelBuilder;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.core.parser.CodeReader;
|
||||
import org.eclipse.cdt.internal.formatter.scanner.Scanner;
|
||||
import org.eclipse.cdt.internal.formatter.scanner.Token;
|
||||
|
||||
/**
|
||||
* A simple model builder for assembly translation units.
|
||||
* Recognizes preprocessor directives (#include and #define)
|
||||
* and labels.
|
||||
*
|
||||
* @see AssemblyLanguage
|
||||
* @since 5.0
|
||||
*/
|
||||
public class AsmModelBuilder implements IContributedModelBuilder {
|
||||
|
||||
private static final class Counter {
|
||||
int fCount;
|
||||
}
|
||||
|
||||
private final static class Tokenizer extends Scanner {
|
||||
public Tokenizer(char[] source) {
|
||||
setSource(source);
|
||||
}
|
||||
|
||||
public Token nextToken() {
|
||||
Token t= super.nextToken();
|
||||
while (t != null && (t.isWhiteSpace())) {
|
||||
t= super.nextToken();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
private TranslationUnit fTranslationUnit;
|
||||
private char fLineSeparatorChar;
|
||||
private HashMap fGlobals;
|
||||
private HashMap fLabels;
|
||||
private int fLastLabelEndOffset;
|
||||
private AsmLabel fLastGlobalLabel;
|
||||
private SourceManipulation fLastLabel;
|
||||
|
||||
/**
|
||||
* Creates a model builder for the given assembly translation unit.
|
||||
*
|
||||
* @param tu the translation unit
|
||||
*/
|
||||
public AsmModelBuilder(ITranslationUnit tu) {
|
||||
fTranslationUnit= (TranslationUnit)tu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the line separator character (in addition to normal newlines).
|
||||
*
|
||||
* @param lineSeparatorChar
|
||||
*/
|
||||
public void setLineSeparatorChar(char lineSeparatorChar) {
|
||||
fLineSeparatorChar= lineSeparatorChar;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see org.eclipse.cdt.core.model.IContributedModelBuilder#parse(boolean)
|
||||
*/
|
||||
public void parse(boolean quickParseMode) throws Exception {
|
||||
CodeReader reader;
|
||||
reader = fTranslationUnit.getCodeReader();
|
||||
if (reader == null) {
|
||||
return;
|
||||
}
|
||||
buildModel(reader.buffer);
|
||||
// not sure whether this is necessary or not
|
||||
fTranslationUnit.setIsStructureKnown(true);
|
||||
fGlobals= null;
|
||||
fLabels= null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the model.
|
||||
*
|
||||
* @param source
|
||||
* @throws CModelException
|
||||
*/
|
||||
private void buildModel(final char[] source) throws CModelException {
|
||||
fGlobals= new HashMap();
|
||||
fLabels= new HashMap();
|
||||
fLastLabel= null;
|
||||
fLastGlobalLabel= null;
|
||||
fLastLabelEndOffset= 0;
|
||||
|
||||
// TLETODO use new Lexer?
|
||||
Scanner scanner= new Scanner();
|
||||
scanner.setSplitPreprocessor(true);
|
||||
scanner.setSource(source);
|
||||
|
||||
// if true the next token is the first on a (logical) line
|
||||
boolean firstTokenOnLine= true;
|
||||
// next token can be an instruction or a label
|
||||
boolean expectInstruction=true;
|
||||
// inside instruction
|
||||
boolean inInstruction= false;
|
||||
|
||||
Token token= scanner.nextToken();
|
||||
while (token != null) {
|
||||
int type= adaptTokenType(token);
|
||||
switch (type) {
|
||||
case Token.tPREPROCESSOR_INCLUDE:
|
||||
parseInclude(fTranslationUnit, token);
|
||||
break;
|
||||
case Token.tPREPROCESSOR_DEFINE:
|
||||
parseDefine(fTranslationUnit, token);
|
||||
break;
|
||||
case Token.tFLOATINGPT:
|
||||
if (token.getText().startsWith(".")) { //$NON-NLS-1$
|
||||
// move scanner behind '.'
|
||||
scanner.setCurrentPosition(scanner.getCurrentTokenStartPosition() + 1);
|
||||
// fallthrough
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
case Token.tDOT:
|
||||
// assembly directive?
|
||||
firstTokenOnLine= false;
|
||||
if (expectInstruction) {
|
||||
expectInstruction= false;
|
||||
int pos= scanner.getCurrentPosition();
|
||||
token= scanner.nextToken();
|
||||
if (token != null && adaptTokenType(token) == Token.tIDENTIFIER) {
|
||||
String text= token.getText();
|
||||
if (isGlobalDirective(text)) {
|
||||
firstTokenOnLine= parseGlobalDirective(token, scanner);
|
||||
} else if (isDataDirective(text)) {
|
||||
inInstruction= true;
|
||||
fLastLabelEndOffset= scanner.getCurrentTokenEndPosition();
|
||||
}
|
||||
} else {
|
||||
scanner.setCurrentPosition(pos);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Token.tIDENTIFIER:
|
||||
// identifier may be a label or part of an instruction
|
||||
if (firstTokenOnLine) {
|
||||
int pos= scanner.getCurrentPosition();
|
||||
int ch= scanner.getNextChar();
|
||||
if (ch == ':') {
|
||||
parseLabel(fTranslationUnit, token);
|
||||
fLastLabelEndOffset= scanner.getCurrentPosition();
|
||||
expectInstruction= true;
|
||||
} else {
|
||||
fLastLabelEndOffset= scanner.getCurrentTokenEndPosition();
|
||||
scanner.setCurrentPosition(pos);
|
||||
expectInstruction= false;
|
||||
inInstruction= true;
|
||||
}
|
||||
firstTokenOnLine= false;
|
||||
} else if (expectInstruction){
|
||||
expectInstruction= false;
|
||||
inInstruction= true;
|
||||
fLastLabelEndOffset= scanner.getCurrentTokenEndPosition();
|
||||
} else if (inInstruction) {
|
||||
fLastLabelEndOffset= scanner.getCurrentTokenEndPosition();
|
||||
}
|
||||
break;
|
||||
case Token.tPREPROCESSOR:
|
||||
case Token.tWHITESPACE:
|
||||
if (!firstTokenOnLine) {
|
||||
int nlIndex= token.getText().indexOf('\n');
|
||||
firstTokenOnLine= nlIndex >= 0;
|
||||
if (firstTokenOnLine && inInstruction) {
|
||||
fLastLabelEndOffset= scanner.getCurrentTokenStartPosition() + nlIndex + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
expectInstruction= false;
|
||||
firstTokenOnLine= false;
|
||||
if (fLineSeparatorChar != 0) {
|
||||
if (token.getLength() == 1 && token.getText().charAt(0) == fLineSeparatorChar) {
|
||||
firstTokenOnLine= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (firstTokenOnLine) {
|
||||
expectInstruction= true;
|
||||
inInstruction= false;
|
||||
}
|
||||
token= scanner.nextToken();
|
||||
}
|
||||
if (!firstTokenOnLine && inInstruction) {
|
||||
fLastLabelEndOffset= scanner.getCurrentTokenEndPosition();
|
||||
}
|
||||
if (fLastLabel != null) {
|
||||
fixupLastLabel();
|
||||
}
|
||||
if (fLastGlobalLabel != null) {
|
||||
fixupLastGlobalLabel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapt non-identifier tokens to identifier type if they look like valid asm words.
|
||||
*
|
||||
* @param token
|
||||
* @return the adapted token type
|
||||
*/
|
||||
private int adaptTokenType(Token token) {
|
||||
int type= token.getType();
|
||||
if (type != Token.tIDENTIFIER) {
|
||||
if (Character.isUnicodeIdentifierStart(token.getText().charAt(0))) {
|
||||
type= Token.tIDENTIFIER;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private boolean isDataDirective(String directive) {
|
||||
return "byte".equals(directive) || "long".equals(directive) || "word".equals(directive) || "ascii".equals(directive); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
|
||||
private boolean parseGlobalDirective(Token token, Scanner scanner) {
|
||||
boolean eol= false;
|
||||
do {
|
||||
Token t= scanner.nextToken();
|
||||
if (t == null) {
|
||||
break;
|
||||
}
|
||||
switch (adaptTokenType(t)) {
|
||||
case Token.tIDENTIFIER:
|
||||
registerGlobalLabel(t.getText());
|
||||
break;
|
||||
case Token.tWHITESPACE:
|
||||
if (token.getText().indexOf('\n') >= 0) {
|
||||
eol= true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (fLineSeparatorChar != 0) {
|
||||
if (token.getLength() == 1 && token.getText().charAt(0) == fLineSeparatorChar) {
|
||||
eol= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!eol);
|
||||
return eol;
|
||||
}
|
||||
|
||||
private boolean isGlobalDirective(String name) {
|
||||
return "globl".equals(name) || "global".equals(name); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
private void registerGlobalLabel(String labelName) {
|
||||
Counter counter= (Counter) fGlobals.get(labelName);
|
||||
if (counter == null) {
|
||||
fGlobals.put(labelName, counter= new Counter());
|
||||
}
|
||||
counter.fCount++;
|
||||
}
|
||||
|
||||
private int getGlobalLabelIndex(String labelName) {
|
||||
Counter counter= (Counter) fGlobals.get(labelName);
|
||||
if (counter == null) {
|
||||
return 0;
|
||||
}
|
||||
return counter.fCount;
|
||||
}
|
||||
|
||||
private int registerLabel(String labelName) {
|
||||
Counter counter= (Counter) fLabels.get(labelName);
|
||||
if (counter == null) {
|
||||
fLabels.put(labelName, counter= new Counter());
|
||||
}
|
||||
return counter.fCount++;
|
||||
}
|
||||
|
||||
private void parseLabel(CElement parent, Token token) throws CModelException {
|
||||
String labelName= token.getText();
|
||||
int index= getGlobalLabelIndex(labelName);
|
||||
boolean global= index > 0;
|
||||
if (!global) {
|
||||
index= registerLabel(labelName);
|
||||
}
|
||||
AsmLabel label= new AsmLabel(parent, labelName, global, index);
|
||||
SourceManipulationInfo labelInfo= label.getSourceManipulationInfo();
|
||||
labelInfo.setIdPos(token.getOffset(), token.getLength());
|
||||
labelInfo.setPos(token.getOffset(), token.getLength());
|
||||
if (fLastLabel != null) {
|
||||
fixupLastLabel();
|
||||
}
|
||||
if (global) {
|
||||
// new global label
|
||||
if (fLastGlobalLabel != null) {
|
||||
fixupLastGlobalLabel();
|
||||
}
|
||||
fLastGlobalLabel= label;
|
||||
} else {
|
||||
// add under global label if available
|
||||
if (fLastGlobalLabel != null) {
|
||||
parent= fLastGlobalLabel;
|
||||
}
|
||||
}
|
||||
fLastLabel= label;
|
||||
parent.addChild(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the body position of the last global label.
|
||||
*
|
||||
* @throws CModelException
|
||||
*/
|
||||
private void fixupLastGlobalLabel() throws CModelException {
|
||||
if (fLastLabel != null && fLastLabel != fLastGlobalLabel) {
|
||||
SourceManipulationInfo globalLabelInfo= fLastGlobalLabel.getSourceManipulationInfo();
|
||||
SourceManipulationInfo labelInfo= fLastLabel.getSourceManipulationInfo();
|
||||
globalLabelInfo.setPos(globalLabelInfo.getStartPos(), labelInfo.getStartPos() + labelInfo.getLength() - globalLabelInfo.getStartPos());
|
||||
// TLETODO set line info
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the body position of the last label.
|
||||
*
|
||||
* @throws CModelException
|
||||
*/
|
||||
private void fixupLastLabel() throws CModelException {
|
||||
if (fLastLabelEndOffset > 0) {
|
||||
SourceManipulationInfo labelInfo= fLastLabel.getSourceManipulationInfo();
|
||||
labelInfo.setPos(labelInfo.getStartPos(), fLastLabelEndOffset - labelInfo.getStartPos());
|
||||
// TLETODO set line info
|
||||
fLastLabelEndOffset= 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void parseDefine(CElement parent, Token token) throws CModelException {
|
||||
final String tokenText= token.getText();
|
||||
Scanner defineScanner= new Tokenizer(tokenText.toCharArray());
|
||||
defineScanner.setCurrentPosition(tokenText.indexOf('#') + 1);
|
||||
int nameStart= 0;
|
||||
int nameEnd= 0;
|
||||
String name= null;
|
||||
Token t= defineScanner.nextToken();
|
||||
if (adaptTokenType(t) == Token.tIDENTIFIER && t.getText().equals("define")) { //$NON-NLS-1$
|
||||
t= defineScanner.nextToken();
|
||||
if (adaptTokenType(t) == Token.tIDENTIFIER) {
|
||||
nameStart= defineScanner.getCurrentTokenStartPosition();
|
||||
nameEnd= defineScanner.getCurrentTokenEndPosition() + 1;
|
||||
name= t.getText();
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return;
|
||||
}
|
||||
Macro macro= new Macro(parent, name);
|
||||
SourceManipulationInfo macroInfo= macro.getSourceManipulationInfo();
|
||||
macroInfo.setIdPos(token.getOffset() + nameStart, nameEnd - nameStart);
|
||||
macroInfo.setPos(token.getOffset(), token.getLength());
|
||||
parent.addChild(macro);
|
||||
}
|
||||
|
||||
private void parseInclude(CElement parent, Token token) throws CModelException {
|
||||
final String tokenText= token.getText();
|
||||
Scanner includeScanner= new Tokenizer(tokenText.toCharArray());
|
||||
includeScanner.setCurrentPosition(tokenText.indexOf('#') + 1);
|
||||
int nameStart= 0;
|
||||
int nameEnd= includeScanner.eofPosition + 1;
|
||||
String name= null;
|
||||
boolean isStandard= false;
|
||||
Token t= includeScanner.nextToken();
|
||||
if (adaptTokenType(t) == Token.tIDENTIFIER) {
|
||||
t= includeScanner.nextToken();
|
||||
if (t.type == Token.tLT) {
|
||||
nameStart= includeScanner.getCurrentTokenStartPosition();
|
||||
do {
|
||||
t= includeScanner.nextToken();
|
||||
} while (t != null && t.type != Token.tGT);
|
||||
nameEnd= includeScanner.getCurrentTokenEndPosition() + 1;
|
||||
name= tokenText.substring(nameStart + 1, nameEnd - 1);
|
||||
} else if (t.type == Token.tSTRING) {
|
||||
nameStart= includeScanner.getCurrentTokenStartPosition();
|
||||
nameEnd= includeScanner.getCurrentTokenEndPosition() + 1;
|
||||
name= t.getText().substring(1, t.getLength() - 1);
|
||||
isStandard= true;
|
||||
} else if (adaptTokenType(t) == Token.tIDENTIFIER) {
|
||||
nameStart= includeScanner.getCurrentTokenStartPosition();
|
||||
nameEnd= includeScanner.getCurrentTokenEndPosition() + 1;
|
||||
name= t.getText();
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return;
|
||||
}
|
||||
Include include= new Include(parent, name, isStandard);
|
||||
SourceManipulationInfo includeInfo= include.getSourceManipulationInfo();
|
||||
includeInfo.setIdPos(token.getOffset() + nameStart, nameEnd - nameStart);
|
||||
includeInfo.setPos(token.getOffset(), token.getLength());
|
||||
parent.addChild(include);
|
||||
}
|
||||
|
||||
}
|
|
@ -36,7 +36,16 @@ public class AssemblyLanguage extends AbstractLanguage {
|
|||
* @see org.eclipse.cdt.core.model.ILanguage#createModelBuilder(org.eclipse.cdt.core.model.ITranslationUnit)
|
||||
*/
|
||||
public IContributedModelBuilder createModelBuilder(ITranslationUnit tu) {
|
||||
return null;
|
||||
IContributedModelBuilder modelBuilder= null;
|
||||
IContributedModelBuilder.Factory modelBuilderFactory= (IContributedModelBuilder.Factory)getAdapter(IContributedModelBuilder.Factory.class);
|
||||
if (modelBuilderFactory != null) {
|
||||
modelBuilder= modelBuilderFactory.create(tu);
|
||||
}
|
||||
if (modelBuilder == null) {
|
||||
// use default
|
||||
modelBuilder= new AsmModelBuilder(tu);
|
||||
}
|
||||
return modelBuilder;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -48,6 +48,7 @@ import org.eclipse.ui.editors.text.EditorsUI;
|
|||
import org.eclipse.ui.ide.IDE;
|
||||
import org.eclipse.ui.ide.ResourceUtil;
|
||||
import org.eclipse.ui.part.FileEditorInput;
|
||||
import org.eclipse.ui.texteditor.ITextEditor;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
|
@ -57,6 +58,7 @@ import org.eclipse.cdt.core.model.IBuffer;
|
|||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.IIncludeReference;
|
||||
import org.eclipse.cdt.core.model.ISourceRange;
|
||||
import org.eclipse.cdt.core.model.ISourceReference;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.core.model.IWorkingCopy;
|
||||
|
@ -133,8 +135,21 @@ public class EditorUtility {
|
|||
* Selects a C Element in an editor
|
||||
*/
|
||||
public static void revealInEditor(IEditorPart part, ICElement element) {
|
||||
if (element != null && part instanceof CEditor) {
|
||||
if (element == null) {
|
||||
return;
|
||||
}
|
||||
if (part instanceof CEditor) {
|
||||
((CEditor) part).setSelection(element);
|
||||
} else if (part instanceof ITextEditor) {
|
||||
if (element instanceof ISourceReference && !(element instanceof ITranslationUnit)) {
|
||||
ISourceReference reference= (ISourceReference) element;
|
||||
try {
|
||||
ISourceRange range= reference.getSourceRange();
|
||||
((ITextEditor)part).selectAndReveal(range.getIdStartPos(), range.getIdLength());
|
||||
} catch (CModelException exc) {
|
||||
CUIPlugin.getDefault().log(exc.getStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue