diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCCompleteExtensionsParseTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCCompleteExtensionsParseTest.java new file mode 100644 index 00000000000..f0525574914 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCCompleteExtensionsParseTest.java @@ -0,0 +1,78 @@ +/********************************************************************** + * Copyright (c) 2004 IBM Canada Ltd. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.core.parser.tests; + +import java.util.Iterator; + +import org.eclipse.cdt.core.parser.ast.ASTUtil; +import org.eclipse.cdt.core.parser.ast.IASTExpression; +import org.eclipse.cdt.core.parser.ast.IASTFunction; +import org.eclipse.cdt.core.parser.ast.IASTSimpleTypeSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTVariable; +import org.eclipse.cdt.core.parser.ast.gcc.IASTGCCExpression; +import org.eclipse.cdt.core.parser.ast.gcc.IASTGCCSimpleTypeSpecifier; + +/** + * @author jcamelon + * + */ +public class GCCCompleteExtensionsParseTest extends CompleteParseBaseTest { + + /** + * + */ + public GCCCompleteExtensionsParseTest() { + super(); + // TODO Auto-generated constructor stub + } + + /** + * @param name + */ + public GCCCompleteExtensionsParseTest(String name) { + super(name); + // TODO Auto-generated constructor stub + } + + public void testBug39695() throws Exception + { + Iterator i = parse("int a = __alignof__ (int);").getDeclarations(); //$NON-NLS-1$ + IASTVariable a = (IASTVariable) i.next(); + assertFalse( i.hasNext() ); + IASTExpression exp = a.getInitializerClause().getAssigmentExpression(); + assertEquals( exp.getExpressionKind(), IASTGCCExpression.Kind.UNARY_ALIGNOF_TYPEID ); + assertEquals( exp.toString(), "__alignof__(int)"); //$NON-NLS-1$ + } + + public void testBug39684() throws Exception + { + IASTFunction bar = (IASTFunction) parse("typeof(foo(1)) bar () { return foo(1); }").getDeclarations().next(); //$NON-NLS-1$ + + IASTSimpleTypeSpecifier simpleTypeSpec = ((IASTSimpleTypeSpecifier)bar.getReturnType().getTypeSpecifier()); + assertEquals( simpleTypeSpec.getType(), IASTGCCSimpleTypeSpecifier.Type.TYPEOF ); + } + + public void testBug39698A() throws Exception + { + Iterator i = parse("int c = a ? b;").getDeclarations(); //$NON-NLS-1$ + IASTVariable c = (IASTVariable) i.next(); + IASTExpression exp = c.getInitializerClause().getAssigmentExpression(); + assertEquals( ASTUtil.getExpressionString( exp ), "a >? b" ); //$NON-NLS-1$ + } + +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCParserExtensionTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCParserExtensionTestSuite.java new file mode 100644 index 00000000000..088e13518c1 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCParserExtensionTestSuite.java @@ -0,0 +1,33 @@ +/********************************************************************** + * Copyright (c) 2004 IBM Canada Ltd. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.core.parser.tests; + +import org.eclipse.cdt.core.parser.tests.scanner2.GCCScannerExtensionsTest; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * @author jcamelon + * + */ +public class GCCParserExtensionTestSuite extends TestCase { + + public static Test suite() { + TestSuite suite= new TestSuite(GCCParserExtensionTestSuite.class.getName()); + suite.addTestSuite( GCCScannerExtensionsTest.class ); + suite.addTestSuite( GCCQuickParseExtensionsTest.class ); + suite.addTestSuite( GCCCompleteExtensionsParseTest.class ); + return suite; + } + +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCQuickParseExtensionsTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCQuickParseExtensionsTest.java new file mode 100644 index 00000000000..85d5d6eef64 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCQuickParseExtensionsTest.java @@ -0,0 +1,92 @@ +/********************************************************************** + * Copyright (c) 2004 IBM Canada Ltd. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.core.parser.tests; + +import java.io.StringWriter; +import java.io.Writer; +import java.util.Iterator; + +import org.eclipse.cdt.core.parser.ast.ASTClassKind; +import org.eclipse.cdt.core.parser.ast.IASTAbstractTypeSpecifierDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTField; +import org.eclipse.cdt.core.parser.ast.IASTFunction; +import org.eclipse.cdt.core.parser.ast.IASTVariable; + +/** + * @author jcamelon + * + */ +public class GCCQuickParseExtensionsTest extends BaseASTTest { + + /** + * @param a + */ + public GCCQuickParseExtensionsTest(String a) { + super(a); + // TODO Auto-generated constructor stub + } + + public void testBug39694() throws Exception + { + IASTVariable variable = (IASTVariable)parse("int ab$cd = 1;").getDeclarations().next(); //$NON-NLS-1$ + assertEquals( variable.getName(), "ab$cd"); //$NON-NLS-1$ + } + + public void testBug39704A() throws Exception + { + IASTVariable foo = (IASTVariable) assertSoleDeclaration("__declspec (dllimport) int foo;"); //$NON-NLS-1$ + assertEquals( foo.getName(), "foo"); //$NON-NLS-1$ + } + public void testBug39704D() throws Exception + { + IASTFunction func1 = (IASTFunction) assertSoleDeclaration("__declspec(dllexport) int func1 (int a) {}"); //$NON-NLS-1$ + assertEquals( func1.getName(), "func1"); //$NON-NLS-1$ + } + + public void testBug39695() throws Exception + { + parse("int a = __alignof__ (int);"); //$NON-NLS-1$ + } + + public void testBug39684() throws Exception + { + parse("typeof(foo(1)) bar () { return foo(1); }"); //$NON-NLS-1$ + } + + public void testBug39703() throws Exception + { + Writer code = new StringWriter(); + code.write("/* __extension__ enables GNU C mode for the duration of the declaration. */\n"); //$NON-NLS-1$ + code.write("__extension__ struct G {\n"); //$NON-NLS-1$ + code.write(" struct { char z; };\n"); //$NON-NLS-1$ + code.write(" char g;\n"); //$NON-NLS-1$ + code.write("};\n"); //$NON-NLS-1$ + IASTAbstractTypeSpecifierDeclaration abs = (IASTAbstractTypeSpecifierDeclaration)assertSoleDeclaration(code.toString()); + IASTClassSpecifier G = ((IASTClassSpecifier)abs.getTypeSpecifier()); + assertEquals( G.getName(), "G" ); //$NON-NLS-1$ + assertEquals( G.getClassKind(), ASTClassKind.STRUCT ); + Iterator i = G.getDeclarations(); + assertEquals( ((IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier()).getName(), "" ); //$NON-NLS-1$ + assertEquals( ((IASTField)i.next()).getName(), "g" ); //$NON-NLS-1$ + assertFalse( i.hasNext() ); + } + + public void testBug39698A() throws Exception + { + parse("int c = a ? b;"); //$NON-NLS-1$ + } + +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner2/GCCScannerExtensionsTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner2/GCCScannerExtensionsTest.java new file mode 100644 index 00000000000..ab9c3a1ac01 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner2/GCCScannerExtensionsTest.java @@ -0,0 +1,36 @@ +/********************************************************************** + * Copyright (c) 2004 IBM Canada Ltd. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.core.parser.tests.scanner2; + +import org.eclipse.cdt.core.parser.IGCCToken; + +/** + * @author jcamelon + * + */ +public class GCCScannerExtensionsTest extends BaseScanner2Test { + + /** + * @param x + */ + public GCCScannerExtensionsTest(String x) { + super(x); + } + + public void testBug39698() throws Exception + { + initializeScanner( "?"); //$NON-NLS-1$ + validateToken( IGCCToken.tMIN ); + validateToken( IGCCToken.tMAX ); + validateEOF(); + } + +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner2/ObjectMapTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner2/ObjectMapTest.java new file mode 100644 index 00000000000..0f894746144 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner2/ObjectMapTest.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* + * Created on Jul 19, 2004 + */ +package org.eclipse.cdt.core.parser.tests.scanner2; + +import junit.framework.TestCase; + +import org.eclipse.cdt.internal.core.parser.scanner2.CharArrayUtils; +import org.eclipse.cdt.internal.core.parser.scanner2.ObjectMap; + +/** + * @author aniefer + */ +public class ObjectMapTest extends TestCase { + + static public class HashObject{ + HashObject( int h ){ + hash = h; + } + public int hashCode(){ + return hash; + } + final public int hash; + } + + public void insertContents( ObjectMap map, Object[][] contents ) throws Exception { + for( int i = 0; i < contents.length; i++ ) + map.put( contents[i][0], contents[i][1] ); + } + + public void assertContents( ObjectMap map, Object[][] contents ) throws Exception { + for( int i = 0; i < contents.length; i++ ){ + assertEquals( map.keyAt(i), contents[i][0] ); + assertEquals( map.getAt(i), contents[i][1] ); + assertEquals( map.get(contents[i][0]), contents[i][1] ); + } + assertEquals( map.size(), contents.length ); + } + + public void testSimpleAdd() throws Exception{ + ObjectMap map = new ObjectMap( 2 ); + + Object [][] contents = new Object[][] { {"1", "ob" } }; //$NON-NLS-1$//$NON-NLS-2$ + + insertContents( map, contents ); + assertContents( map, contents ); + + assertEquals( map.size(), 1 ); + assertEquals( map.capacity(), 2 ); + } + + public void testSimpleCollision() throws Exception{ + ObjectMap map = new ObjectMap( 2 ); + + HashObject key1 = new HashObject( 1 ); + HashObject key2 = new HashObject( 1 ); + + Object [][] contents = new Object[][] { {key1, "1" }, //$NON-NLS-1$ + {key2, "2" } }; //$NON-NLS-1$ + + insertContents( map, contents ); + + assertEquals( map.size(), 2 ); + assertEquals( map.capacity(), 2 ); + + assertContents( map, contents ); + } + + public void testResize() throws Exception{ + ObjectMap map = new ObjectMap( 1 ); + + assertEquals( map.size(), 0 ); + assertEquals( map.capacity(), 1 ); + + Object [][] res = new Object [][] { { "0", "o0" }, //$NON-NLS-1$//$NON-NLS-2$ + { "1", "o1" }, //$NON-NLS-1$//$NON-NLS-2$ + { "2", "o2" }, //$NON-NLS-1$//$NON-NLS-2$ + { "3", "o3" }, //$NON-NLS-1$//$NON-NLS-2$ + { "4", "o4" } }; //$NON-NLS-1$//$NON-NLS-2$ + + insertContents( map, res ); + assertEquals( map.capacity(), 8 ); + assertContents( map, res ); + } + + public void testCollisionResize() throws Exception{ + ObjectMap map = new ObjectMap( 1 ); + + assertEquals( map.size(), 0 ); + assertEquals( map.capacity(), 1 ); + + Object [][] res = new Object [][] { { new HashObject(0), "o0" }, //$NON-NLS-1$ + { new HashObject(1), "o1" }, //$NON-NLS-1$ + { new HashObject(0), "o2" }, //$NON-NLS-1$ + { new HashObject(1), "o3" }, //$NON-NLS-1$ + { new HashObject(0), "o4" } }; //$NON-NLS-1$ + + insertContents( map, res ); + assertEquals( map.capacity(), 8 ); + assertContents( map, res ); + } + + public void testReAdd() throws Exception{ + ObjectMap map = new ObjectMap( 1 ); + + assertEquals( map.size(), 0 ); + assertEquals( map.capacity(), 1 ); + + Object [][] res = new Object [][] { { "0", "o0" }, //$NON-NLS-1$ //$NON-NLS-2$ + { "1", "o1" } }; //$NON-NLS-1$ //$NON-NLS-2$ + + insertContents( map, res ); + assertEquals( map.capacity(), 2 ); + assertContents( map, res ); + + res = new Object [][]{ { "0", "o00" }, //$NON-NLS-1$ //$NON-NLS-2$ + { "1", "o01" }, //$NON-NLS-1$ //$NON-NLS-2$ + { "10", "o10" }, //$NON-NLS-1$ //$NON-NLS-2$ + { "11", "o11" } }; //$NON-NLS-1$ //$NON-NLS-2$ + + insertContents( map, res ); + assertContents( map, res ); + } + + public void testResizeResolvesCollision() throws Exception{ + ObjectMap map = new ObjectMap( 2 ); + + Object k1 = new HashObject( 0 ); + Object k2 = new HashObject( 1 ); + Object k3 = new HashObject( 4 ); //collision with 0 in a table capacity 2, but ok in table capacity 4 + + Object [][] con = new Object[][] { { k1, "1" }, //$NON-NLS-1$ + { k2, "2" }, //$NON-NLS-1$ + { k3, "3" } } ; //$NON-NLS-1$ + + insertContents( map, con ); + assertContents( map, con ); + } + + public void testCharArrayUtils() throws Exception{ + char [] buffer = "A::B::C".toCharArray(); //$NON-NLS-1$ + + assertEquals( CharArrayUtils.lastIndexOf( "::".toCharArray(), buffer ), 4 ); //$NON-NLS-1$ + assertTrue( CharArrayUtils.equals( CharArrayUtils.lastSegment( buffer, "::".toCharArray()), "C".toCharArray() ) ); //$NON-NLS-1$ //$NON-NLS-2$ + + buffer = "A::B::C:foo".toCharArray(); //$NON-NLS-1$ + assertEquals( CharArrayUtils.lastIndexOf( "::".toCharArray(), buffer ), 4 ); //$NON-NLS-1$ + assertTrue( CharArrayUtils.equals( CharArrayUtils.lastSegment( buffer, "::".toCharArray()), "C:foo".toCharArray() ) ); //$NON-NLS-1$ //$NON-NLS-2$ + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/BasicTypeInfo.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/BasicTypeInfo.java new file mode 100644 index 00000000000..294edb4adee --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/BasicTypeInfo.java @@ -0,0 +1,312 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* + * Created on Jul 5, 2004 + */ +package org.eclipse.cdt.internal.core.parser.pst; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.ListIterator; + + +/** + * @author aniefer + */ +public class BasicTypeInfo implements ITypeInfo { + + public void setBit( boolean b, int mask ) { + if( b ){ + _typeBits = _typeBits | mask; + } else { + _typeBits = _typeBits & ~mask; + } + } + + public boolean checkBit( int mask ) { + return (_typeBits & mask) != 0; + } + + public void setType( ITypeInfo.eType t ) { + _type = t; + } + + public ITypeInfo.eType getType() { + return _type; + } + + public boolean isType( ITypeInfo.eType type ) { + return isType( type, t_undef ); + } + + public int getTypeBits() { + return _typeBits; + } + + public void setTypeBits( int typeInfo ) { + _typeBits = typeInfo; + } + + /** + * + * @param infoProvider - TypeInfoProvider to use if pooling the TypeInfo created, if null, + * pooling is not used. If pooling is used, TypeInfoProvider.returnTypeInfo + * must be called when the TypeInfo is no longer needed + * @return + */ + public ITypeInfo getFinalType( TypeInfoProvider infoProvider ) { + return ParserSymbolTable.getFlatTypeInfo( this, infoProvider ); + } + + /** + * + * @param type + * @param upperType + * @return boolean + * + * type checking, check that this declaration's type is between type and + * upperType (inclusive). upperType of 0 means no range and our type must + * be type. + */ + public boolean isType( ITypeInfo.eType type, ITypeInfo.eType upperType ) { + //type of -1 means we don't care + if( type == t_any ) + return true; + + //upperType of 0 means no range + if( upperType == t_undef ){ + return ( getType() == type ); + } + return ( getType().compareTo( type ) >= 0 && getType().compareTo( upperType ) <= 0 ); + } + + + + public boolean hasPtrOperators() { + return _ptrOperators.size() > 0; + } + + public List getPtrOperators() { + return _ptrOperators; + } + + public boolean hasSamePtrs( ITypeInfo type ) { + int size = getPtrOperators().size(); + int size2 = type.getPtrOperators().size(); + ITypeInfo.PtrOp ptr1 = null, ptr2 = null; + + if( size == size2 ){ + if( size > 0 ){ + for( int i = 0; i < size; i++ ){ + ptr1 = (ITypeInfo.PtrOp)getPtrOperators().get(i); + ptr2 = (ITypeInfo.PtrOp)type.getPtrOperators().get(i); + if( ptr1.getType() != ptr2.getType() ){ + return false; + } + } + } + return true; + } + return false; + } + + public void applyOperatorExpression( ITypeInfo.OperatorExpression op ) { + if( op == null ) + return; + + if( op == ITypeInfo.OperatorExpression.indirection || + op == ITypeInfo.OperatorExpression.subscript ) + { + //indirection operator, can only be applied to a pointer + //subscript should be applied to something that is "pointer to T", the result is a lvalue of type "T" + if( hasPtrOperators() ){ + ListIterator iterator = getPtrOperators().listIterator( getPtrOperators().size() ); + ITypeInfo.PtrOp last = (ITypeInfo.PtrOp)iterator.previous(); + if( last.getType() == ITypeInfo.PtrOp.t_pointer || + last.getType() == ITypeInfo.PtrOp.t_array ) + { + iterator.remove(); + } + } + } else if( op == ITypeInfo.OperatorExpression.addressof ){ + //Address-of unary operator, results in pointer to T + //TODO or pointer to member + ITypeInfo.PtrOp newOp = new ITypeInfo.PtrOp( ITypeInfo.PtrOp.t_pointer ); + addPtrOperator( newOp ); + } + } + + public void addPtrOperator( ITypeInfo.PtrOp ptr ) { + if( ptr != null ){ + if( _ptrOperators == Collections.EMPTY_LIST ){ + _ptrOperators = new ArrayList(4); + } + + _ptrOperators.add( ptr ); + } + } + + public void addPtrOperator( List ptrs ) { + if( ptrs == null || ptrs.size() == 0 ) + return; + + if( _ptrOperators == Collections.EMPTY_LIST ){ + _ptrOperators = new ArrayList( ptrs.size() ); + } + + int size = ptrs.size(); + for( int i = 0; i < size; i++ ){ + _ptrOperators.add( ptrs.get( i ) ); + } + } + + public void preparePtrOperators( int numPtrOps ) { + if( _ptrOperators == Collections.EMPTY_LIST ) + _ptrOperators = new ArrayList( numPtrOps ); + else + ((ArrayList) _ptrOperators).ensureCapacity( numPtrOps ); + } + + + /** + * canHold + * @param type + * @return boolean + * return true if our type can hold all the values of the passed in + * type. + * TODO, for now return true if our type is "larger" (based on ordering of + * the type values) + */ + public boolean canHold( ITypeInfo type ) { + if( getType().compareTo( type.getType()) > 0 ){ + return true; + } + int mask = isShort | isLong | isLongLong; + return ( getTypeBits() & mask ) >= ( type.getTypeBits() & mask ); + } + + public boolean equals( Object t ) { + if( t == null || !(t instanceof ITypeInfo) ){ + return false; + } + + ITypeInfo type = (ITypeInfo)t; + + int bits1 = _typeBits & ~isTypedef & ~isForward & ~isStatic & ~isExtern; + int bits2 = type.getTypeBits() & ~isTypedef & ~isForward & ~isStatic & ~isExtern; + boolean result = ( bits1 == bits2 ); + + result &= ( _type == type.getType() ); + +// Object def1 = getDefault(); +// Object def2 = type.getDefault(); +// result &= ( (def1 == null && def2 == null) || +// (def1 != null && def2 != null && def1.equals( def2 )) ); +// + if( !result ) + return false; + + int size1 = _ptrOperators.size(); + int size2 = type.getPtrOperators().size(); + if( size1 == size2 ){ + if( size1 != 0 ){ + ITypeInfo.PtrOp op1 = null, op2 = null; + for( int i = 0; i < size1; i++ ){ + op1 = (ITypeInfo.PtrOp)_ptrOperators.get(i); + op2 = (ITypeInfo.PtrOp)type.getPtrOperators().get(i); + + if( !op1.equals(op2) ){ + return false; + } + } + } + } else { + return false; + } + + return result; + } + + private static final char _image[][] = { ParserSymbolTable.EMPTY_NAME_ARRAY, //$NON-NLS-1$ t_undef + ParserSymbolTable.EMPTY_NAME_ARRAY, //t_type + "namespace".toCharArray(), //$NON-NLS-1$ t_namespace + "class".toCharArray(), //$NON-NLS-1$ t_class + "struct".toCharArray(), //$NON-NLS-1$ t_struct + "union".toCharArray(), //$NON-NLS-1$ t_union + "enum".toCharArray(), //$NON-NLS-1$ t_enumeration + ParserSymbolTable.EMPTY_NAME_ARRAY, //t_constructor + ParserSymbolTable.EMPTY_NAME_ARRAY, //t_function + "_Bool".toCharArray(), //$NON-NLS-1$ t__Bool + "bool".toCharArray(), //$NON-NLS-1$ t_bool + "char".toCharArray(), //$NON-NLS-1$ t_char + "wchar_t".toCharArray(), //$NON-NLS-1$ t_wchar_t + "int".toCharArray(), //$NON-NLS-1$ t_int + "float".toCharArray(), //$NON-NLS-1$ t_float + "double".toCharArray(), //$NON-NLS-1$ t_double + "void".toCharArray(), //$NON-NLS-1$ t_void + ParserSymbolTable.EMPTY_NAME_ARRAY, //t_enumerator + ParserSymbolTable.EMPTY_NAME_ARRAY, //t_block + "template".toCharArray(), //$NON-NLS-1$ t_template + ParserSymbolTable.EMPTY_NAME_ARRAY, //t_asm + ParserSymbolTable.EMPTY_NAME_ARRAY, //t_linkage + ParserSymbolTable.EMPTY_NAME_ARRAY, //t_templateParameter + "typename".toCharArray() //$NON-NLS-1$ t_typeName + }; + + public char[] toCharArray() { + if( isType( t_type ) && getTypeSymbol() != null ){ + return getTypeSymbol().getName(); + } + return _image[ getType().toInt() ]; + } + + public void clear() { + _typeBits = 0; + _type = t_undef; + _ptrOperators = Collections.EMPTY_LIST; + } + + public void copy( ITypeInfo t ) { + if( t == null ) + return; + _typeBits = t.getTypeBits(); + _type = t.getType(); + + if( t.getPtrOperators() != Collections.EMPTY_LIST ) + _ptrOperators = (ArrayList)((ArrayList)t.getPtrOperators()).clone(); + else + _ptrOperators = Collections.EMPTY_LIST; + } + + public boolean getHasDefault(){ + return _hasDefault; + } + public void setHasDefault( boolean def ){ + _hasDefault = def; + } + + /** + * The following functions are implemented in derived classes + */ + public ITypeInfo.eType getTemplateParameterType() { return ITypeInfo.t_undef; } + public void setTemplateParameterType( ITypeInfo.eType type ) { throw new UnsupportedOperationException(); } + public ISymbol getTypeSymbol() { return null; } + public void setTypeSymbol( ISymbol type ) { if( type != null ) throw new UnsupportedOperationException(); } + public void setDefault( Object t ) { if( t != null ) throw new UnsupportedOperationException(); } + public Object getDefault() { return null; } + + protected int _typeBits = 0; + protected ITypeInfo.eType _type = t_undef; + protected List _ptrOperators = Collections.EMPTY_LIST; + protected boolean _hasDefault = false; +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITypeInfo.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITypeInfo.java new file mode 100644 index 00000000000..15174f4c919 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITypeInfo.java @@ -0,0 +1,254 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* + * Created on Jul 5, 2004 + */ +package org.eclipse.cdt.internal.core.parser.pst; + +import java.util.List; + +import org.eclipse.cdt.core.parser.Enum; + +/** + * @author aniefer + */ +public interface ITypeInfo { + public static class OperatorExpression extends Enum{ + + //5.3.1-1 : The unary * operator, the expression to which it is applied shall be + //a pointer to an object type or a pointer to a function type and the result + //is an lvalue refering to the object or function to which the expression points + public static final OperatorExpression indirection = new OperatorExpression( 1 ); + + //5.3.1-2 : The result of the unary & operator is a pointer to its operand + public static final OperatorExpression addressof = new OperatorExpression( 0 ); + + //5.2.1 A postfix expression followed by an expression in square brackets is a postfix + //expression. one of the expressions shall have the type "pointer to T" and the other + //shall have a enumeration or integral type. The result is an lvalue of type "T" + public static final OperatorExpression subscript = new OperatorExpression( 2 ); + + protected OperatorExpression(int enumValue) { + super(enumValue); + } + } + + public static class PtrOp { + public PtrOp( eType type ){ + this.type = type; + } + public PtrOp( eType type, boolean isConst, boolean isVolatile ){ + this.type = type; + this.isConstPtr = isConst; + this.isVolatilePtr = isVolatile; + } + public PtrOp( ISymbol memberOf, boolean isConst, boolean isVolatile ){ + this.type = PtrOp.t_memberPointer; + this.isConstPtr = isConst; + this.isVolatilePtr = isVolatile; + this.memberOf = memberOf; + } + + public PtrOp(){ + super(); + } + + public static final eType t_undef_ptr = new eType( 0 ); + public static final eType t_pointer = new eType( 1 ); + public static final eType t_reference = new eType( 2 ); + public static final eType t_array = new eType( 3 ); + public static final eType t_memberPointer = new eType( 4 ); + + public eType getType() { return type; } + public void setType( eType type ) { this.type = type; } + + public boolean isConst() { return isConstPtr; } + public boolean isVolatile() { return isVolatilePtr; } + public void setConst( boolean isConst ) { this.isConstPtr = isConst; } + public void setVolatile(boolean isVolatile) { this.isVolatilePtr = isVolatile; } + + public ISymbol getMemberOf() { return memberOf; } + public void setMemberOf( ISymbol member ) { this.memberOf = member; } + + public int compareCVTo( ITypeInfo.PtrOp ptr ){ + int cv1 = ( isConst() ? 1 : 0 ) + ( isVolatile() ? 1 : 0 ); + int cv2 = ( ptr.isConst() ? 1 : 0 ) + ( ptr.isVolatile() ? 1 : 0 ); + + return cv1 - cv2; + } + public boolean equals( Object o ){ + if( o == null || !(o instanceof ITypeInfo.PtrOp) ){ + return false; + } + ITypeInfo.PtrOp op = (ITypeInfo.PtrOp)o; + + return ( isConst() == op.isConst() && + isVolatile() == op.isVolatile() && + getType() == op.getType() ); + } + + private eType type = PtrOp.t_undef_ptr; + private boolean isConstPtr = false; + private boolean isVolatilePtr = false; + private ISymbol memberOf = null; + } + + public static class eType extends Enum implements Comparable{ + protected eType( int v ){ + super( v ); + } + + public int compareTo( Object o ){ + ITypeInfo.eType t = (ITypeInfo.eType) o; + return getEnumValue() - t.getEnumValue(); + } + public int toInt() { + return getEnumValue(); + } + } + + public static final int isAuto = 1 << 0; + public static final int isRegister = 1 << 1; + public static final int isStatic = 1 << 2; + public static final int isExtern = 1 << 3; + public static final int isMutable = 1 << 4; + public static final int isInline = 1 << 5; + public static final int isVirtual = 1 << 6; + public static final int isExplicit = 1 << 7; + public static final int isTypedef = 1 << 8; + public static final int isFriend = 1 << 9; + public static final int isConst = 1 << 10; + public static final int isVolatile = 1 << 11; + public static final int isUnsigned = 1 << 12; + public static final int isShort = 1 << 13; + public static final int isLong = 1 << 14; + public static final int isForward = 1 << 15; + public static final int isComplex = 1 << 16; + public static final int isImaginary = 1 << 17; + public static final int isLongLong = 1 << 18; + public static final int isSigned = 1 << 19; + + // Types + // Note that these should be considered ordered and if you change + // the order, you should consider the ParserSymbolTable uses + public static final ITypeInfo.eType t_any = new ITypeInfo.eType( -1 ); //don't care + public static final ITypeInfo.eType t_undef = new ITypeInfo.eType( 0 ); //not specified + public static final ITypeInfo.eType t_type = new ITypeInfo.eType( 1 ); //Type Specifier + public static final ITypeInfo.eType t_namespace = new ITypeInfo.eType( 2 ); + public static final ITypeInfo.eType t_class = new ITypeInfo.eType( 3 ); + public static final ITypeInfo.eType t_struct = new ITypeInfo.eType( 4 ); + public static final ITypeInfo.eType t_union = new ITypeInfo.eType( 5 ); + public static final ITypeInfo.eType t_enumeration = new ITypeInfo.eType( 6 ); + public static final ITypeInfo.eType t_constructor = new ITypeInfo.eType( 7 ); + public static final ITypeInfo.eType t_function = new ITypeInfo.eType( 8 ); + public static final ITypeInfo.eType t__Bool = new ITypeInfo.eType( 9 ); + public static final ITypeInfo.eType t_bool = new ITypeInfo.eType( 10 ); + public static final ITypeInfo.eType t_char = new ITypeInfo.eType( 11 ); + public static final ITypeInfo.eType t_wchar_t = new ITypeInfo.eType( 12 ); + public static final ITypeInfo.eType t_int = new ITypeInfo.eType( 13 ); + public static final ITypeInfo.eType t_float = new ITypeInfo.eType( 14 ); + public static final ITypeInfo.eType t_double = new ITypeInfo.eType( 15 ); + public static final ITypeInfo.eType t_void = new ITypeInfo.eType( 16 ); + public static final ITypeInfo.eType t_enumerator = new ITypeInfo.eType( 17 ); + public static final ITypeInfo.eType t_block = new ITypeInfo.eType( 18 ); + public static final ITypeInfo.eType t_template = new ITypeInfo.eType( 19 ); + public static final ITypeInfo.eType t_asm = new ITypeInfo.eType( 20 ); + public static final ITypeInfo.eType t_linkage = new ITypeInfo.eType( 21 ); + public static final ITypeInfo.eType t_templateParameter = new ITypeInfo.eType( 22 ); + + public static final ITypeInfo.eType t_typeName = new ITypeInfo.eType( 23 ); + + public abstract void setBit( boolean b, int mask ); + + public abstract boolean checkBit( int mask ); + + public abstract void setType( ITypeInfo.eType t ); + + public abstract ITypeInfo.eType getType(); + + public abstract boolean isType( ITypeInfo.eType type ); + + public abstract int getTypeBits(); + + public abstract void setTypeBits( int typeInfo ); + + public abstract ITypeInfo.eType getTemplateParameterType(); + + public abstract void setTemplateParameterType( ITypeInfo.eType type ); + + /** + * + * @param infoProvider - TypeInfoProvider to use if pooling the TypeInfo created, if null, + * pooling is not used. If pooling is used, TypeInfoProvider.returnTypeInfo + * must be called when the TypeInfo is no longer needed + * @return + */ + public abstract ITypeInfo getFinalType( TypeInfoProvider infoProvider ); + + /** + * + * @param type + * @param upperType + * @return boolean + * + * type checking, check that this declaration's type is between type and + * upperType (inclusive). upperType of 0 means no range and our type must + * be type. + */ + public abstract boolean isType( ITypeInfo.eType type, + ITypeInfo.eType upperType ); + + public abstract ISymbol getTypeSymbol(); + + public abstract void setTypeSymbol( ISymbol type ); + + public abstract boolean hasPtrOperators(); + + public abstract List getPtrOperators(); + + public abstract boolean hasSamePtrs( ITypeInfo type ); + + public abstract void applyOperatorExpression( ITypeInfo.OperatorExpression op ); + + public abstract void addPtrOperator( ITypeInfo.PtrOp ptr ); + + public abstract void addPtrOperator( List ptrs ); + + public abstract void preparePtrOperators( int numPtrOps ); + + public abstract boolean getHasDefault(); + + public abstract void setHasDefault( boolean def ); + + public abstract void setDefault( Object t ); + + public abstract Object getDefault(); + + /** + * canHold + * @param type + * @return boolean + * return true if our type can hold all the values of the passed in + * type. + * TODO, for now return true if our type is "larger" (based on ordering of + * the type values) + */ + public abstract boolean canHold( ITypeInfo type ); + + public abstract boolean equals( Object t ); + + public abstract char[] toCharArray(); + + public abstract void clear(); + + public abstract void copy( ITypeInfo t ); +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/CharArraySet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/CharArraySet.java new file mode 100644 index 00000000000..1e38478d067 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/CharArraySet.java @@ -0,0 +1,295 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* + * Created on Jul 21, 2004 + */ +package org.eclipse.cdt.internal.core.parser.scanner2; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author aniefer + */ +public class CharArraySet { + private char[][] keyTable; + private int[] hashTable; + private int[] nextTable; + + private int currEntry = -1; + + public static final CharArraySet EMPTY_SET = new CharArraySet( 0 ){ + public Object clone() { return this; } + public List toList() { return Collections.EMPTY_LIST; } + public void put( char[] key ) { throw new UnsupportedOperationException(); } + public void addAll( List list ) { throw new UnsupportedOperationException(); } + public void addAll( CharArraySet set ) { throw new UnsupportedOperationException(); } + }; + + public CharArraySet(int initialSize) { + int size = 1; + while (size < initialSize) + size <<= 1; + + keyTable = new char[size][]; + hashTable = new int[size * 2]; + nextTable = new int[size]; + } + + public void put(char[] key ){ + add(key); + } + + public void addAll( List list ){ + if( list == null ) + return; + + int size = list.size(); + for( int i = 0; i < size; i++ ){ + add( (char[]) list.get( i ) ); + } + } + + public void addAll( CharArraySet set ){ + if( set == null ) + return; + int size = set.size(); + for( int i = 0; i < size; i++ ){ + add( set.keyAt( i ) ); + } + } + + public List toList(){ + List list = new ArrayList( size() ); + int size = size(); + for( int i = 0; i < size; i++ ){ + list.add( keyAt( i ) ); + } + return list; + } + + final public boolean remove( char[] key ) { + int i = lookup(key); + if (i < 0) + return false; + + removeEntry(i); + return true; + } + + /** + * @return + */ + final public boolean isEmpty() { + return currEntry == -1; + } + +// public Object clone(){ +// HashTable newTable = null; +// try { +// newTable = (HashTable) super.clone(); +// } catch ( CloneNotSupportedException e ) { +// //shouldn't happen because object supports clone. +// return null; +// } +// +// int size = capacity(); +// newTable.keyTable = new Object[ size ]; +// newTable.hashTable = new int[ size*2 ]; +// newTable.nextTable = new int[ size ]; +// +// System.arraycopy(keyTable, 0, newTable.keyTable, 0, keyTable.length); +// System.arraycopy(hashTable, 0, newTable.hashTable, 0, hashTable.length); +// System.arraycopy(nextTable, 0, newTable.nextTable, 0, nextTable.length); +// +// newTable.currEntry = currEntry; +// return newTable; +// } + + final public int size(){ + return currEntry + 1; + } + + final public char[] keyAt( int i ){ + if( i < 0 || i > currEntry ) + return null; + + return keyTable[ i ]; + } + + final public boolean containsKey( char[] key ){ + return lookup( key ) != -1; + } + +// public Object [] keyArray(){ +// Object [] keys = new Object[ size() ]; +// System.arraycopy( keyTable, 0, keys, 0, keys.length ); +// return keys; +// } + final public void clear(){ + for( int i = 0; i < keyTable.length; i++ ){ + keyTable[i] = null; + hashTable[ 2*i ] = 0; + hashTable[ 2*i + 1 ] = 0; + nextTable[i] = 0; + } + currEntry = -1; + } + + final public int capacity() { + return keyTable.length; + } + + private int hash( char[] obj ){ + return CharArrayUtils.hash( obj ) & (hashTable.length - 1); + } + + private void insert(int i) { + insert(i, hash(keyTable[i])); + } + + private void insert(int i, int hash) { + + if (hashTable[hash] == 0) { + hashTable[hash] = i + 1; + } else { + // need to link + int j = hashTable[hash] - 1; + while (nextTable[j] != 0) + j = nextTable[j] - 1; + nextTable[j] = i + 1; + } + } + + private void resize(int size) { + Object[] oldKeyTable = keyTable; + keyTable = new char[size][]; + System.arraycopy(oldKeyTable, 0, keyTable, 0, oldKeyTable.length); + + // Need to rehash everything + rehash( oldKeyTable.length, true ); + } + + private void rehash( int n, boolean reallocate ){ + if( reallocate ){ + hashTable = new int[ keyTable.length * 2 ]; + nextTable = new int[ keyTable.length ]; + } else { + for( int i = 0; i < keyTable.length; i++ ){ + hashTable[2*i] = 0; + hashTable[2*i+1] = 0; + nextTable[i] = 0; + } + } + for (int i = 0; i < n; ++i) { + insert(i); + } + } + + private void resize() { + resize(keyTable.length << 1); + } + + private int add(char[] obj) { + int hash = hash(obj); + + if (hashTable[hash] == 0) { + if ( (currEntry + 1) >= keyTable.length){ + resize(); + //hash code needs to be recomputed, just recurse. + return add( obj ); + } + currEntry++; + keyTable[currEntry] = obj; + insert(currEntry, hash); + return currEntry; + } + // is the key already registered? + int i = hashTable[hash] - 1; + if ( CharArrayUtils.equals( obj, keyTable[i] ) ) + // yup + return i; + + // follow the next chain + int last = i; + for (i = nextTable[i] - 1; i >= 0; i = nextTable[i] - 1) { + if ( CharArrayUtils.equals( obj, keyTable[i] ) ) + // yup this time + return i; + last = i; + } + + // nope, add it in + if ( (currEntry + 1) >= keyTable.length){ + resize(); + //hash code needs to be recomputed, just recurse. + return add( obj ); + } + currEntry++; + keyTable[currEntry] = obj; + nextTable[last] = currEntry + 1; + return currEntry; + } + + private void removeEntry(int i) { + // Remove the hash entry + int hash = hash(keyTable[i]); + if (hashTable[hash] == i + 1) + hashTable[hash] = nextTable[i]; + else { + // find entry pointing to me + int j = hashTable[hash] - 1; + while (nextTable[j] != 0 && nextTable[j] != i + 1) + j = nextTable[j] - 1; + nextTable[j] = nextTable[i]; + } + + if (i < currEntry) { + // shift everything over + System.arraycopy(keyTable, i + 1, keyTable, i, currEntry - i); + System.arraycopy(nextTable, i + 1, nextTable, i, currEntry - i); + + // adjust hash and next entries for things that moved + for (int j = 0; j < hashTable.length; ++j) + if (hashTable[j] > i + 1) + --hashTable[j]; + + for (int j = 0; j < nextTable.length; ++j) + if (nextTable[j] > i + 1) + --nextTable[j]; + } + + // last entry is now free + keyTable[currEntry] = null; + nextTable[currEntry] = 0; + --currEntry; + } + + private int lookup(char[] buffer ){ + int hash = hash(buffer); + + if (hashTable[hash] == 0) + return -1; + + int i = hashTable[hash] - 1; + if ( CharArrayUtils.equals( buffer, keyTable[i] ) ) + return i; + + // Follow the next chain + for (i = nextTable[i] - 1; i >= 0; i = nextTable[i] - 1) + if ( CharArrayUtils.equals( buffer, keyTable[i] ) ) + return i; + + return -1; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/HashTable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/HashTable.java new file mode 100644 index 00000000000..7cc6d50c31d --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/HashTable.java @@ -0,0 +1,240 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* + * For use by the Parser Symbol Table + * Created on Jul 15, 2004 + */ +package org.eclipse.cdt.internal.core.parser.scanner2; + + +/** + * @author aniefer + */ +public abstract class HashTable implements Cloneable{ + + protected Object[] keyTable; + private int[] hashTable; + private int[] nextTable; + + + protected int currEntry = -1; + + public HashTable(int initialSize) { + int size = 1; + while (size < initialSize) + size <<= 1; + + keyTable = new Object[size]; + hashTable = new int[size * 2]; + nextTable = new int[size]; + } + + public Object clone(){ + HashTable newTable = null; + try { + newTable = (HashTable) super.clone(); + } catch ( CloneNotSupportedException e ) { + //shouldn't happen because object supports clone. + return null; + } + + int size = capacity(); + newTable.keyTable = new Object[ size ]; + newTable.hashTable = new int[ size*2 ]; + newTable.nextTable = new int[ size ]; + + System.arraycopy(keyTable, 0, newTable.keyTable, 0, keyTable.length); + System.arraycopy(hashTable, 0, newTable.hashTable, 0, hashTable.length); + System.arraycopy(nextTable, 0, newTable.nextTable, 0, nextTable.length); + + newTable.currEntry = currEntry; + return newTable; + } + + public int size(){ + return currEntry + 1; + } + + public Object keyAt( int i ){ + if( i < 0 || i > currEntry ) + return null; + + return keyTable[ i ]; + } + + public void clear(){ + for( int i = 0; i < keyTable.length; i++ ){ + keyTable[i] = null; + hashTable[ 2*i ] = 0; + hashTable[ 2*i + 1 ] = 0; + nextTable[i] = 0; + } + currEntry = -1; + } + + public int capacity() { + return keyTable.length; + } + + private int hash(Object obj) { + return obj.hashCode() & (hashTable.length - 1); + } + + private void insert(int i) { + insert(i, hash(keyTable[i])); + } + + private void insert(int i, int hash) { + + if (hashTable[hash] == 0) { + hashTable[hash] = i + 1; + } else { + // need to link + int j = hashTable[hash] - 1; + while (nextTable[j] != 0) + j = nextTable[j] - 1; + nextTable[j] = i + 1; + } + } + + protected void resize(int size) { + Object[] oldKeyTable = keyTable; + keyTable = new Object[size]; + System.arraycopy(oldKeyTable, 0, keyTable, 0, oldKeyTable.length); + + // Need to rehash everything + rehash( oldKeyTable.length, true ); + } + + protected void rehash( int n, boolean reallocate ){ + if( reallocate ){ + hashTable = new int[ keyTable.length * 2 ]; + nextTable = new int[ keyTable.length ]; + } else { + for( int i = 0; i < keyTable.length; i++ ){ + hashTable[2*i] = 0; + hashTable[2*i+1] = 0; + nextTable[i] = 0; + } + } + for (int i = 0; i < n; ++i) { + insert(i); + } + } + + private void resize() { + resize(keyTable.length << 1); + } + + protected final int add(Object obj) { + int hash = hash(obj); + + if (hashTable[hash] == 0) { + if ( (currEntry + 1) >= keyTable.length){ + resize(); + //hash code needs to be recomputed, just recurse. + return add( obj ); + } + currEntry++; + keyTable[currEntry] = obj; + insert(currEntry, hash); + return currEntry; + } + // is the key already registered? + int i = hashTable[hash] - 1; + if ( obj.equals( keyTable[i] ) ) + // yup + return i; + + // follow the next chain + int last = i; + for (i = nextTable[i] - 1; i >= 0; i = nextTable[i] - 1) { + if (obj.equals( keyTable[i] ) ) + // yup this time + return i; + last = i; + } + + // nope, add it in + if ( (currEntry + 1) >= keyTable.length){ + resize(); + //hash code needs to be recomputed, just recurse. + return add( obj ); + } + currEntry++; + keyTable[currEntry] = obj; + nextTable[last] = currEntry + 1; + return currEntry; + } + + protected void removeEntry(int i) { + // Remove the hash entry + int hash = hash(keyTable[i]); + if (hashTable[hash] == i + 1) + hashTable[hash] = nextTable[i]; + else { + // find entry pointing to me + int j = hashTable[hash] - 1; + while (nextTable[j] != 0 && nextTable[j] != i + 1) + j = nextTable[j] - 1; + nextTable[j] = nextTable[i]; + } + + if (i < currEntry) { + // shift everything over + System.arraycopy(keyTable, i + 1, keyTable, i, currEntry - i); + System.arraycopy(nextTable, i + 1, nextTable, i, currEntry - i); + + // adjust hash and next entries for things that moved + for (int j = 0; j < hashTable.length; ++j) + if (hashTable[j] > i + 1) + --hashTable[j]; + + for (int j = 0; j < nextTable.length; ++j) + if (nextTable[j] > i + 1) + --nextTable[j]; + } + + // last entry is now free + keyTable[currEntry] = null; + nextTable[currEntry] = 0; + --currEntry; + } + + protected final int lookup(Object buffer ){ + int hash = hash(buffer); + + if (hashTable[hash] == 0) + return -1; + + int i = hashTable[hash] - 1; + if (buffer.equals( keyTable[i] ) ) + return i; + + // Follow the next chain + for (i = nextTable[i] - 1; i >= 0; i = nextTable[i] - 1) + if ( buffer.equals( keyTable[i] )) + return i; + + return -1; + } + + public boolean containsKey( Object key ){ + return lookup( key ) != -1; + } + + public Object [] keyArray(){ + Object [] keys = new Object[ size() ]; + System.arraycopy( keyTable, 0, keys, 0, keys.length ); + return keys; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectMap.java new file mode 100644 index 00000000000..ed97f76734c --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectMap.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* + * cloned from CharArrayMap & CharArrayObjectMap + * Created on Jul 14, 2004 + */ +package org.eclipse.cdt.internal.core.parser.scanner2; + +import java.util.Comparator; + +/** + * @author aniefer + */ +public class ObjectMap extends HashTable{ + public static final ObjectMap EMPTY_MAP = new ObjectMap( 0 ){ + public Object clone() { return this; } + public Object put( Object key, Object value ) { throw new UnsupportedOperationException(); } + }; + + private Object[] valueTable; + + public ObjectMap(int initialSize) { + super( initialSize ); + + valueTable = new Object[ capacity() ]; + } + + public Object clone(){ + ObjectMap newMap = (ObjectMap) super.clone(); + + newMap.valueTable = new Object[ capacity() ]; + + System.arraycopy(valueTable, 0, newMap.valueTable, 0, valueTable.length); + return newMap; + } + + final public void clear(){ + super.clear(); + for( int i = 0; i < valueTable.length; i++ ){ + valueTable[i] = null; + } + } + + protected void resize(int size) { + Object[] oldValueTable = valueTable; + valueTable = new Object[size]; + System.arraycopy(oldValueTable, 0, valueTable, 0, oldValueTable.length); + + super.resize( size ); + } + + public Object put(Object key, Object value) { + int i = add(key); + Object oldvalue = valueTable[i]; + valueTable[i] = value; + return oldvalue; + } + + final public Object get(Object key) { + int i = lookup(key); + if (i >= 0) + return valueTable[i]; + return null; + } + + final public Object getAt( int i ){ + if( i < 0 || i > currEntry ) + return null; + +// return get( keyAt( i ) ); + return valueTable[i]; + } + + final public boolean isEmpty(){ + return currEntry == -1; + } + + final public Object remove( Object key ) { + if( key == null ) + return null; + int i = lookup(key); + if (i < 0) + return null; + + Object value = valueTable[i]; + removeEntry(i); + + return value; + } + + final protected void removeEntry(int i) { + // Remove the entry from the valueTable, shifting everything over if necessary + if (i < currEntry) + System.arraycopy(valueTable, i + 1, valueTable, i, currEntry - i); + valueTable[currEntry] = null; + + // Make sure you remove the value before calling super where currEntry will change + super.removeEntry(i); + } + + final public void sort( Comparator c ) { + if( size() > 1 ){ + quickSort( c, 0, size() - 1 ); + + rehash( size(), false ); + } + } + + private void quickSort( Comparator c, int p, int r ){ + if( p < r ){ + int q = partition( c, p, r ); + if( p < q ) quickSort( c, p, q ); + if( ++q < r ) quickSort( c, q, r ); + } + } + private int partition( Comparator c, int p, int r ){ + Object x = keyTable[ p ]; + Object temp = null; + int i = p; + int j = r; + + while( true ){ + while( c.compare( keyTable[ j ], x ) > 0 ){ j--; } + if( i < j ) + while( c.compare( keyTable[ i ], x ) < 0 ){ i++; } + + if( i < j ){ + temp = keyTable[j]; + keyTable[j] = keyTable[i]; + keyTable[i] = temp; + + temp = valueTable[j]; + valueTable[j] = valueTable[i]; + valueTable[i] = temp; + } else { + return j; + } + } + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectSet.java new file mode 100644 index 00000000000..f4f9582cc6d --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectSet.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* + * Created on Jul 15, 2004 + */ +package org.eclipse.cdt.internal.core.parser.scanner2; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author aniefer + */ +public class ObjectSet extends HashTable{ + public static final ObjectSet EMPTY_SET = new ObjectSet( 0 ){ + public Object clone() { return this; } + public List toList() { return Collections.EMPTY_LIST; } + public void put( Object key ) { throw new UnsupportedOperationException(); } + public void addAll( List list ) { throw new UnsupportedOperationException(); } + public void addAll( ObjectSet set ) { throw new UnsupportedOperationException(); } + }; + + public ObjectSet(int initialSize) { + super( initialSize ); + } + + public void put(Object key ){ + add(key); + } + + public void addAll( List list ){ + if( list == null ) + return; + + int size = list.size(); + for( int i = 0; i < size; i++ ){ + add( list.get( i ) ); + } + } + + public void addAll( ObjectSet set ){ + if( set == null ) + return; + int size = set.size(); + for( int i = 0; i < size; i++ ){ + add( set.keyAt( i ) ); + } + } + + public List toList(){ + List list = new ArrayList( size() ); + int size = size(); + for( int i = 0; i < size; i++ ){ + list.add( keyAt( i ) ); + } + return list; + } + + public boolean remove( Object key ) { + int i = lookup(key); + if (i < 0) + return false; + + removeEntry(i); + return true; + } + + /** + * @return + */ + public boolean isEmpty() { + return currEntry == -1; + } +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/ParserTimeOut.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/ParserTimeOut.java new file mode 100644 index 00000000000..b471351b7bc --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/ParserTimeOut.java @@ -0,0 +1,126 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.core.parser; + +import org.eclipse.cdt.core.parser.IParser; + +/** + * @author bgheorgh + * + */ +public class ParserTimeOut implements Runnable { + + + protected Thread thread; + protected boolean enabled; + protected IParser cancellable; + private int timeout = 0; + private int threadPriority = Thread.MIN_PRIORITY + 1; + boolean debug = false; + private String threadName = null; + boolean readyToRun = true; + + public ParserTimeOut(){ + reset(); + } + + public ParserTimeOut(String threadName){ + this.threadName = threadName; + reset(); + } + + public void run() { + while (this.thread != null) { + try { + synchronized(this){ + if (enabled){ + readyToRun = false; + wait(timeout); + if (enabled){ + if(cancellable != null) + cancellable.cancel(); + enabled = false; + } + } + else{ + while(!enabled){ + readyToRun = true; + wait(); + } + } + } + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + public synchronized void startTimer(){ + enabled = true; + notify(); + } + + public synchronized void stopTimer(){ + enabled= false; + notify(); + } + + + + public void reset() { + enabled=false; + if (threadName!=null){ + thread = new Thread(this, threadName); + } + else{ + thread = new Thread(this, "Time Out Thread"); //$NON-NLS-1$ + } + thread.setDaemon(true); + thread.setPriority(threadPriority); + thread.start(); + } + /** + * @return Returns the threadPriority. + */ + public int getThreadPriority() { + return threadPriority; + } + /** + * @param threadPriority The threadPriority to set. + */ + public void setThreadPriority(int threadPriority) { + this.threadPriority = threadPriority; + } + + /** + * @param pm The pm to set. + */ + public void setParser(IParser c) { + this.cancellable = c; + } + /** + * @return Returns the timeout. + */ + public int getTimeout() { + return timeout; + } + /** + * @param timeout The timeout to set. + */ + public void setTimeout(int timeout) { + this.timeout = timeout; + } + + public boolean isReadyToRun(){ + return readyToRun; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinerProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinerProvider.java new file mode 100644 index 00000000000..7f8012f422b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinerProvider.java @@ -0,0 +1,163 @@ +/********************************************************************** + * Copyright (c) 2002,2003,2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.ui.editor; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ElementChangedEvent; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICElementDelta; +import org.eclipse.cdt.core.model.IElementChangedListener; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.internal.ui.BaseCElementContentProvider; +import org.eclipse.cdt.ui.PreferenceConstants; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.Viewer; + +/* + * CContentOutlinerProvider + */ +public class CContentOutlinerProvider extends BaseCElementContentProvider { + + CContentOutlinePage fOutliner; + ITranslationUnit root; + private ElementChangedListener fListener; + private IPropertyChangeListener fPropertyListener; + + /** + * The element change listener of the java outline viewer. + * @see IElementChangedListener + */ + class ElementChangedListener implements IElementChangedListener { + + public void elementChanged(final ElementChangedEvent e) { + + ICElementDelta delta= findElement(root, e.getDelta()); + if (delta != null && fOutliner != null) { + fOutliner.contentUpdated(); + return; + } + // TODO: We should be able to be smarter then a dum refresh +// ICElementDelta delta= findElement(base, e.getDelta()); +// if (delta != null && fOutlineViewer != null) { +// fOutlineViewer.reconcile(delta); +// } + } + + private boolean isPossibleStructuralChange(ICElementDelta cuDelta) { + if (cuDelta.getKind() != ICElementDelta.CHANGED) { + return true; // add or remove + } + int flags= cuDelta.getFlags(); + if ((flags & ICElementDelta.F_CHILDREN) != 0) { + return true; + } + return (flags & (ICElementDelta.F_CONTENT | ICElementDelta.F_FINE_GRAINED)) == ICElementDelta.F_CONTENT; + } + + protected ICElementDelta findElement(ICElement unit, ICElementDelta delta) { + + if (delta == null || unit == null) + return null; + + ICElement element= delta.getElement(); + + if (unit.equals(element)) { + if (isPossibleStructuralChange(delta)) { + return delta; + } + return null; + } + + if (element.getElementType() > ICElement.C_UNIT) + return null; + + ICElementDelta[] children= delta.getAffectedChildren(); + if (children == null || children.length == 0) + return null; + + for (int i= 0; i < children.length; i++) { + ICElementDelta d= findElement(unit, children[i]); + if (d != null) + return d; + } + + return null; + } + } + + class PropertyListener implements IPropertyChangeListener { + + /* (non-Javadoc) + * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + String prop = event.getProperty(); + if (prop.equals(PreferenceConstants.OUTLINE_GROUP_INCLUDES)) { + Object newValue = event.getNewValue(); + if (newValue instanceof Boolean) { + boolean value = ((Boolean)newValue).booleanValue(); + if (areIncludesGroup() != value) { + setIncludesGrouping(value); + if (fOutliner != null) { + fOutliner.contentUpdated(); + } + } + } + } + } + + } + + /** + * + */ + public CContentOutlinerProvider(CContentOutlinePage outliner) { + super(true, true); + fOutliner = outliner; + setIncludesGrouping(PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.OUTLINE_GROUP_INCLUDES)); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + super.dispose(); + if (fListener != null) { + CoreModel.getDefault().removeElementChangedListener(fListener); + fListener= null; + } + if (fPropertyListener != null) { + PreferenceConstants.getPreferenceStore().removePropertyChangeListener(fPropertyListener); + fPropertyListener = null; + } + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + boolean isTU= (newInput instanceof ITranslationUnit); + + if (isTU && fListener == null) { + root = (ITranslationUnit)newInput; + fListener= new ElementChangedListener(); + CoreModel.getDefault().addElementChangedListener(fListener); + fPropertyListener = new PropertyListener(); + PreferenceConstants.getPreferenceStore().addPropertyChangeListener(fPropertyListener); + } else if (!isTU && fListener != null) { + CoreModel.getDefault().removeElementChangedListener(fListener); + fListener= null; + root = null; + } + } + +}