| /******************************************************************************* |
| * Copyright (c) 2009, 2010 Nokia 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: |
| * Nokia - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.cdt.debug.edc.symbols; |
| |
| import java.math.BigInteger; |
| |
| import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.IArrayDimensionType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IAggregate; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IArrayBoundType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IArrayType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.ICompositeType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IConstType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IForwardTypeReference; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IPointerType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IQualifierType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IReferenceType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.ISubroutineType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.ITypedef; |
| |
| |
| /* |
| * Various utility routines for Type objects |
| */ |
| public class TypeUtils { |
| |
| // type IDs for basic C and C++ types |
| static public final int BASIC_TYPE_CHAR = 1; |
| static public final int BASIC_TYPE_CHAR_UNSIGNED = 2; |
| static public final int BASIC_TYPE_CHAR_SIGNED = 3; |
| static public final int BASIC_TYPE_SHORT = 4; |
| static public final int BASIC_TYPE_SHORT_UNSIGNED = 5; |
| static public final int BASIC_TYPE_INT = 6; |
| static public final int BASIC_TYPE_INT_UNSIGNED = 7; |
| static public final int BASIC_TYPE_LONG = 8; |
| static public final int BASIC_TYPE_LONG_UNSIGNED = 9; |
| static public final int BASIC_TYPE_LONG_LONG = 10; |
| static public final int BASIC_TYPE_LONG_LONG_UNSIGNED = 11; |
| static public final int BASIC_TYPE_FLOAT = 12; |
| static public final int BASIC_TYPE_FLOAT_COMPLEX = 13; |
| static public final int BASIC_TYPE_DOUBLE = 14; |
| static public final int BASIC_TYPE_DOUBLE_COMPLEX = 15; |
| static public final int BASIC_TYPE_LONG_DOUBLE = 16; |
| static public final int BASIC_TYPE_LONG_DOUBLE_COMPLEX = 17; |
| static public final int BASIC_TYPE_BOOL = 18; |
| static public final int BASIC_TYPE_BOOL_C9X = 19; |
| static public final int BASIC_TYPE_WCHAR_T = 20; |
| static public final int BASIC_TYPE_POINTER = 21; // not technically a basic type |
| |
| // is a type a pointer "*" type? |
| public static boolean isPointerType(IType type) { |
| return getStrippedType(type) instanceof IPointerType; |
| } |
| |
| // is a type a reference "&" type? |
| public static boolean isReferenceType(IType type) { |
| return getStrippedType(type) instanceof IReferenceType; |
| } |
| |
| // is a type an aggregate (composite or array) type? |
| public static boolean isAggregateType(IType type) { |
| return getStrippedType(type) instanceof IAggregate; |
| } |
| |
| // is a type a composite (class, struct, or union) type? |
| public static boolean isCompositeType(IType type) { |
| return getStrippedType(type) instanceof ICompositeType; |
| } |
| |
| /** |
| * is a type a constant type? |
| * @since 2.0 |
| */ |
| public static boolean isConstType(IType type) { |
| if (type instanceof IForwardTypeReference) |
| type = ((IForwardTypeReference) type).getReferencedType(); |
| |
| while ( type instanceof ITypedef || type instanceof IQualifierType || type instanceof IReferenceType |
| || type instanceof IArrayType) { |
| if (type instanceof IConstType) |
| return true; |
| |
| type = type.getType(); |
| |
| if (type instanceof IForwardTypeReference) |
| type = ((IForwardTypeReference) type).getReferencedType(); |
| } |
| |
| return false; |
| } |
| |
| // return the type with no typedefs, consts, or volatiles |
| public static IType getStrippedType(IType type) { |
| if (type instanceof IForwardTypeReference) |
| type = ((IForwardTypeReference) type).getReferencedType(); |
| |
| while (type instanceof ITypedef || type instanceof IQualifierType) { |
| type = type.getType(); |
| |
| if (type instanceof IForwardTypeReference) |
| type = ((IForwardTypeReference) type).getReferencedType(); |
| } |
| |
| return type; |
| } |
| |
| /** |
| * Return the type with no typedefs, consts, volatiles, or references |
| * @since 2.0 |
| */ |
| public static IType getUnRefStrippedType(IType type) { |
| if (type instanceof IForwardTypeReference) |
| type = ((IForwardTypeReference) type).getReferencedType(); |
| |
| while (type instanceof ITypedef || type instanceof IQualifierType || type instanceof IReferenceType) { |
| type = type.getType(); |
| |
| if (type instanceof IForwardTypeReference) |
| type = ((IForwardTypeReference) type).getReferencedType(); |
| } |
| |
| return type; |
| } |
| |
| // return base type with no typedefs, consts, volatiles, or pointer types |
| // removing array types messes up formatters because they are assumed to act on the array |
| // but code creating expressions ignores the array syntax |
| // unlike with pointer types where -> is used instead of . |
| public static IType getBaseType(Object type) { |
| if (!(type instanceof IType)) |
| return null; |
| |
| if (type instanceof IForwardTypeReference) |
| type = ((IForwardTypeReference) type).getReferencedType(); |
| |
| while (type instanceof ITypedef || type instanceof IQualifierType |
| || type instanceof IPointerType) { |
| type = ((IType) type).getType(); |
| |
| if (type instanceof IForwardTypeReference) |
| type = ((IForwardTypeReference) type).getReferencedType(); |
| } |
| |
| return (IType) type; |
| } |
| |
| // return base type with no consts, volatiles, pointer types, or array types - but preserving typedefs |
| public static IType getBaseTypePreservingTypedef(IType type) { |
| if (type instanceof IForwardTypeReference) |
| type = ((IForwardTypeReference) type).getReferencedType(); |
| |
| while (type instanceof IQualifierType |
| || type instanceof IPointerType || type instanceof IArrayType) { |
| type = type.getType(); |
| |
| if (type instanceof IForwardTypeReference) |
| type = ((IForwardTypeReference) type).getReferencedType(); |
| } |
| |
| return type; |
| } |
| |
| // shift, mask, and extend an extracted bit-field |
| // NOTE: this may need to be endianness aware |
| public static Number extractBitField(Number value, int byteSize, int bitSize, int bitOffset, boolean isSignedInt) { |
| if (bitSize <= 0 || value == null |
| || (!(value instanceof Long) && !(value instanceof Integer) && !(value instanceof BigInteger))) { |
| return value; |
| } |
| |
| // TODO: Need to get default type sizes from the ITargetEnvironment |
| // This assumes long and long long are 64 bits, and int is 32 bits |
| if (value instanceof Long) { |
| long longValue = (Long) value; |
| |
| longValue >>= (byteSize * 8) - (bitOffset + bitSize); |
| longValue &= (-1) >>> (64 - bitSize); |
| |
| if (isSignedInt) { |
| if ((longValue & (1 << (bitSize - 1))) != 0) { |
| longValue |= ((-1) >>> bitSize) << bitSize; |
| } |
| } |
| return new Long(longValue); |
| } |
| |
| if (value instanceof Integer) { |
| int intValue = (Integer) value; |
| |
| intValue >>= (byteSize * 8) - (bitOffset + bitSize); |
| intValue &= ((-1) >>> (32 - bitSize)); |
| |
| if (isSignedInt) { |
| if ((intValue & (1 << (bitSize - 1))) != 0) { |
| intValue |= ((-1) >>> bitSize) << bitSize; |
| } |
| } |
| return new Integer(intValue); |
| } |
| |
| if (value instanceof BigInteger) { |
| BigInteger bigValue = (BigInteger) value; |
| bigValue = bigValue.shiftRight((byteSize * 8) - (bitOffset + bitSize)); |
| byte[] bytes = new byte[8]; |
| int mask; |
| BigInteger bigMask; |
| |
| mask = ((-1) >>> (32 - bitSize)); |
| for (int i = 0; i < 8; i++) { |
| bytes[i] = (byte) ((mask >>> ((7 - i) * 8)) & 0xff); |
| } |
| |
| bigMask = new BigInteger(bytes); |
| bigValue = bigValue.and(bigMask); |
| |
| if (isSignedInt) { |
| // NOTE: for variable values, we use BigInteger ONLY for |
| // unsigned numbers |
| if (bigValue.testBit(bitSize - 1)) { |
| mask = (((-1) >>> bitSize) << bitSize); |
| for (int i = 0; i < 8; i++) { |
| bytes[i] = (byte) ((mask >>> ((7 - i) * 8)) & 0xff); |
| } |
| |
| bigMask = new BigInteger(bytes); |
| bigValue = bigValue.or(bigMask); |
| } |
| } |
| |
| return bigValue; |
| } |
| |
| return value; |
| } |
| |
| /** |
| * Get the full name of a type. |
| * |
| * {@link TypeEngine#getTypeName(IType)} caches the full name returned by this routine and associates it |
| * with the type passed in. |
| * |
| * @param type type whose full name is desired |
| * @return full name of the type, with all qualifiers, array bounds, etc. |
| * |
| * @since 2.0 |
| */ |
| public static String getFullTypeName(IType type) { |
| if (type == null) |
| return ""; //$NON-NLS-1$ |
| if (type instanceof IReferenceType) |
| return getFullTypeName(((IReferenceType) type).getType()) + " &"; //$NON-NLS-1$ |
| if (type instanceof IPointerType) { |
| IType pointedTo = ((IPointerType) type).getType(); |
| if (pointedTo instanceof ISubroutineType) |
| // TODO: get parameters instead of saying "..." |
| return "(*)(...)"; //$NON-NLS-1$ |
| else |
| return getFullTypeName(pointedTo) + " *"; //$NON-NLS-1$ |
| } |
| if (type instanceof IArrayType) { |
| IArrayType arrayType = (IArrayType) type; |
| |
| IType subtype = null; |
| String dimensions = ""; |
| do { |
| for (IArrayBoundType bound : arrayType.getBounds()) |
| dimensions += "[" + bound.getBoundCount() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
| subtype = TypeUtils.getStrippedType(arrayType.getType()); |
| if (subtype instanceof IArrayType) |
| arrayType = (IArrayType)subtype; |
| } while (subtype instanceof IArrayType); |
| |
| return getFullTypeName(arrayType.getType()) + dimensions; |
| } |
| if (type instanceof IArrayDimensionType) { |
| IArrayDimensionType arrayDimensionType = (IArrayDimensionType) type; |
| IArrayType arrayType = arrayDimensionType.getArrayType(); |
| String returnType = getFullTypeName(arrayType.getType()); |
| |
| IArrayBoundType[] bounds = arrayType.getBounds(); |
| for (int i = arrayDimensionType.getDimensionCount(); i < arrayType.getBoundsCount(); i++) { |
| returnType += "[" + bounds[i].getBoundCount() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| return returnType; |
| } |
| if (type instanceof ITypedef) |
| return ((ITypedef) type).getName(); |
| if (type instanceof ICompositeType) |
| return ((ICompositeType) type).getName(); |
| if (type instanceof IQualifierType) |
| return ((IQualifierType) type).getName() |
| + " " + getFullTypeName(((IQualifierType) type).getType()); //$NON-NLS-1$ |
| if (type instanceof ISubroutineType) { |
| // TODO: real stuff once we parse parameters |
| return getFullTypeName(((ISubroutineType) type).getType()); |
| } |
| return type.getName() + getFullTypeName(type.getType()); |
| } |
| |
| /** |
| * Check if a type is an opaque type. |
| * |
| * @param type |
| * @return true if the type is an opaque composite type; false otherwise. |
| * @since 3.0 |
| */ |
| public static boolean isOpaqueType(IType type) { |
| return (type != null && type instanceof ICompositeType && ((ICompositeType)type).isOpaque()); |
| } |
| } |