/******************************************************************************* | |
* Copyright (c) 2009, 2010, 2011 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 | |
* Broadcom - additional JavaDoc | |
*******************************************************************************/ | |
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()); | |
} | |
} |