Opaque strings and variable length data-types

This commit is contained in:
caheckman 2020-04-22 18:23:20 -04:00
parent 2c547ac41b
commit 547a4f2ab5
5 changed files with 211 additions and 76 deletions

View file

@ -234,7 +234,12 @@ Datatype *CastStrategyC::castStandard(Datatype *reqtype,Datatype *curtype,
if (curtype == reqtype) return (Datatype *)0; // Different typedefs could point to the same type
if ((reqbase->getMetatype()==TYPE_VOID)||(reqbase->getMetatype()==TYPE_VOID))
return (Datatype *)0; // Don't cast from or to VOID
if (reqbase->getSize() != curbase->getSize()) return reqtype; // Always cast change in size
if (reqbase->getSize() != curbase->getSize()) {
if (reqbase->isVariableLength() && isptr && reqbase->hasSameVariableBase(curbase)) {
return (Datatype *)0; // Don't need a cast
}
return reqtype; // Otherwise, always cast change in size
}
switch(reqbase->getMetatype()) {
case TYPE_UNKNOWN:
return (Datatype *)0;

View file

@ -1223,7 +1223,7 @@ bool PrintC::printCharacterConstant(ostream &s,const Address &addr,Datatype *cha
const vector<uint1> &buffer(manager->getStringData(addr, charType, isTrunc));
if (buffer.empty())
return false;
if (doEmitWideCharPrefix() && charType->getSize() > 1)
if (doEmitWideCharPrefix() && charType->getSize() > 1 && !charType->isOpaqueString())
s << 'L'; // Print symbol indicating wide character
s << '"';
escapeCharacterData(s,buffer.data(),buffer.size(),1,glb->translate->isBigEndian());

View file

@ -63,6 +63,20 @@ void print_data(ostream &s,uint1 *buffer,int4 size,const Address &baseaddr)
}
}
/// If \b this and the other given data-type are both variable length and come from the
/// the same base data-type, return \b true.
/// \param ct is the other given data-type to compare with \b this
/// \return \b true if they are the same variable length data-type.
bool Datatype::hasSameVariableBase(const Datatype *ct) const
{
if (!isVariableLength()) return false;
if (!ct->isVariableLength()) return false;
uint8 thisId = hashSize(id, size);
uint8 themId = hashSize(ct->id, ct->size);
return (thisId == themId);
}
/// Print a raw description of the type to stream. Intended for debugging.
/// Not intended to produce parsable C.
/// \param s is the output stream
@ -240,8 +254,13 @@ void Datatype::saveXmlBasic(ostream &s) const
{
a_v(s,"name",name);
if (id != 0) {
s << " id=\"0x" << hex << id << '\"';
uint8 saveId;
if (isVariableLength())
saveId = hashSize(id, size);
else
saveId = id;
if (saveId != 0) {
s << " id=\"0x" << hex << saveId << '\"';
}
a_v_i(s,"size",size);
string metastring;
@ -249,6 +268,10 @@ void Datatype::saveXmlBasic(ostream &s) const
a_v(s,"metatype",metastring);
if ((flags & coretype)!=0)
a_v_b(s,"core",true);
if (isVariableLength())
a_v_b(s,"varlength",true);
if ((flags & opaque_string)!=0)
a_v_b(s,"opaquestring",true);
}
/// Write a simple reference to \b this data-type as an XML \<typeref> tag,
@ -283,18 +306,31 @@ void Datatype::restoreXmlBasic(const Element *el)
metatype = string2metatype( el->getAttributeValue("metatype") );
id = 0;
for(int4 i=0;i<el->getNumAttributes();++i) {
if (el->getAttributeName(i) == "core") {
const string &attribName( el->getAttributeName(i) );
if (attribName == "core") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= coretype;
}
else if (el->getAttributeName(i) == "id") {
else if (attribName == "id") {
istringstream i1(el->getAttributeValue(i));
i1.unsetf(ios::dec | ios::hex | ios::oct);
i1 >> id;
}
else if (attribName == "varlength") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= variable_length;
}
else if (attribName == "opaquestring") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= opaque_string;
}
}
if ((id==0)&&(name.size()>0)) // If there is a type name
id = hashName(name); // There must be some kind of id
if (isVariableLength()) {
// Id needs to be unique compared to another data-type with the same name
id = hashSize(id, size);
}
}
/// Restore a Datatype object from an XML element
@ -326,6 +362,21 @@ uint8 Datatype::hashName(const string &nm)
return res;
}
/// This allows IDs for variable length structures to be uniquefied based on size.
/// A base ID is given and a size of the specific instance. A unique ID is returned.
/// The hashing is reversible by feeding the output ID back into this function with the same size.
/// \param id is the given ID to (de)uniquify
/// \param size is the instance size of the structure
/// \param return the (de)uniquified id
uint8 Datatype::hashSize(uint8 id,int4 size)
{
uint8 sizeHash = size;
sizeHash *= 0x98251033aecbabaf; // Hash the size
id ^= sizeHash;
return id;
}
void TypeChar::saveXml(ostream &s) const
{
@ -1483,8 +1534,9 @@ Datatype *TypeFactory::setName(Datatype *ct,const string &n)
/// \param fd is the list of fields to set
/// \param ot is the TypeStruct object to modify
/// \param fixedsize is 0 or the forced size of the structure
/// \param flags are other flags to set on the structure
/// \return true if modification was successful
bool TypeFactory::setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize)
bool TypeFactory::setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize,uint4 flags)
{
int4 offset,cursize,curalign;
@ -1529,6 +1581,7 @@ bool TypeFactory::setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize)
tree.erase(ot);
ot->setFields(fd);
ot->flags |= (flags & (Datatype::opaque_string | Datatype::variable_length));
if (fixedsize > 0) { // If the caller is trying to force a size
if (fixedsize > ot->size) // If the forced size is bigger than the size required for fields
ot->size = fixedsize; // Force the bigger size
@ -2073,20 +2126,27 @@ Datatype *TypeFactory::restoreXmlTypeNoRef(const Element *el,bool forcecore)
int4 num = el->getNumAttributes();
uint8 newid = 0;
int4 structsize = 0;
bool isVarLength = false;
for(int4 i=0;i<num;++i) {
if (el->getAttributeName(i) == "id") {
const string &attribName(el->getAttributeName(i));
if (attribName == "id") {
istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> newid;
}
else if (el->getAttributeName(i) == "size") {
else if (attribName == "size") {
istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> structsize;
}
else if (attribName == "varlength") {
isVarLength = xml_readbool(el->getAttributeValue(i));
}
}
if (newid == 0)
newid = Datatype::hashName(structname);
if (isVarLength)
newid = Datatype::hashSize(newid, structsize);
ct = findByIdLocal(structname,newid);
bool stubfirst = false;
if (ct == (Datatype *)0) {
@ -2105,7 +2165,7 @@ Datatype *TypeFactory::restoreXmlTypeNoRef(const Element *el,bool forcecore)
throw LowlevelError("Redefinition of structure: "+structname);
}
else // If structure is a placeholder stub
if (!setFields(ts.field,(TypeStruct *)ct,ts.size)) // Define structure now by copying fields
if (!setFields(ts.field,(TypeStruct *)ct,ts.size,ts.flags)) // Define structure now by copying fields
throw LowlevelError("Bad structure definition");
}
break;

View file

@ -73,7 +73,9 @@ protected:
enumtype = 4, ///< An enumeration type (as well as an integer)
poweroftwo = 8, ///< An enumeration type where all values are of 2^^n form
utf16 = 16, ///< 16-bit wide chars in unicode UTF16
utf32 = 32 ///< 32-bit wide chars in unicode UTF32
utf32 = 32, ///< 32-bit wide chars in unicode UTF32
opaque_string = 64, ///< Structure that should be treated as a string
variable_length = 128 ///< May be other structures with same name different lengths
};
friend class TypeFactory;
friend struct DatatypeCompare;
@ -85,6 +87,7 @@ protected:
void restoreXmlBasic(const Element *el); ///< Recover basic data-type properties
virtual void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore data-type from XML
static uint8 hashName(const string &nm); ///< Produce a data-type id by hashing the type name
static uint8 hashSize(uint8 id,int4 size); ///< Reversibly hash size into id
public:
/// Construct the base data-type copying low-level properties of another
Datatype(const Datatype &op) { size = op.size; name=op.name; metatype=op.metatype; flags=op.flags; id=op.id; }
@ -94,12 +97,15 @@ public:
Datatype(int4 s,type_metatype m,const string &n) { name=n; size=s; metatype=m; flags=0; id=0; }
virtual ~Datatype(void) {} ///< Destructor
bool isCoreType(void) const { return ((flags&coretype)!=0); } ///< Is this a core data-type
bool isCharPrint(void) const { return ((flags&(chartype|utf16|utf32))!=0); } ///< Does this print as a 'char'
bool isCharPrint(void) const { return ((flags&(chartype|utf16|utf32|opaque_string))!=0); } ///< Does this print as a 'char'
bool isEnumType(void) const { return ((flags&enumtype)!=0); } ///< Is this an enumerated type
bool isPowerOfTwo(void) const { return ((flags&poweroftwo)!=0); } ///< Is this a flag-based enumeration
bool isASCII(void) const { return ((flags&chartype)!=0); } ///< Does this print as an ASCII 'char'
bool isUTF16(void) const { return ((flags&utf16)!=0); } ///< Does this print as UTF16 'wchar'
bool isUTF32(void) const { return ((flags&utf32)!=0); } ///< Does this print as UTF32 'wchar'
bool isVariableLength(void) const { return ((flags&variable_length)!=0); } ///< Is \b this a variable length structure
bool hasSameVariableBase(const Datatype *ct) const; ///< Are these the same variable length data-type
bool isOpaqueString(void) const { return ((flags&opaque_string)!=0); } ///< Is \b this an opaquely encoded string
uint4 getInheritable(void) const { return (flags & coretype); } ///< Get properties pointers inherit
type_metatype getMetatype(void) const { return metatype; } ///< Get the type \b meta-type
uint8 getId(void) const { return id; } ///< Get the type id
@ -412,7 +418,7 @@ public:
Architecture *getArch(void) const { return glb; } ///< Get the Architecture object
Datatype *findByName(const string &n); ///< Return type of given name
Datatype *setName(Datatype *ct,const string &n); ///< Set the given types name
bool setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize); ///< Set fields on a TypeStruct
bool setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize,uint4 flags); ///< Set fields on a TypeStruct
bool setEnumValues(const vector<string> &namelist,
const vector<uintb> &vallist,
const vector<bool> &assignlist,

View file

@ -318,12 +318,43 @@ public class PcodeDataTypeManager {
throw new IllegalArgumentException("Unsupported character size");
}
private String buildTypeInternal(DataType type, int size) { // Build all of type except name attribute
if (type instanceof TypeDef) {
type = ((TypeDef) type).getBaseDataType();
private void appendOpaqueString(StringBuilder resBuf, DataType type, int size) {
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "struct");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeBooleanAttribute(resBuf, "opaquestring", true);
SpecXmlUtils.encodeBooleanAttribute(resBuf, "varlength", true);
resBuf.append(">\n");
resBuf.append("<field name=\"unknown_data1\"");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "offset", 0);
resBuf.append("> <typeref name=\"byte\"/></field>\n");
size -= 1;
resBuf.append("<field name=\"opaque_data\"");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "offset", 1);
resBuf.append("> <type");
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size);
resBuf.append("><typeref name=\"byte\"/></type>");
resBuf.append("</field>\n");
}
private String buildTypeInternal(DataType origType, int size) { // Build all of type except name attribute
DataType type;
if (origType instanceof TypeDef) {
type = ((TypeDef) origType).getBaseDataType();
}
else {
type = origType;
}
StringBuilder resBuf = new StringBuilder();
if (type instanceof Pointer) {
if (origType == type) {
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
}
else {
appendNameIdAttributes(resBuf, origType);
}
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "ptr");
int ptrLen = type.getLength();
if (ptrLen <= 0) {
@ -344,26 +375,35 @@ public class PcodeDataTypeManager {
if (ptrto == null) {
ptrtoTypeRef = buildTypeRef(DefaultDataType.dataType, 1);
}
else if ((ptrto instanceof StringDataType) ||
(type instanceof TerminatedStringDataType)) { // Convert pointer to string
ptrtoTypeRef = getCharTypeRef(dataOrganization.getCharSize()); // to pointer to char
}
else if (ptrto instanceof StringUTF8DataType) { // Convert pointer to string
// TODO: Need to ensure that UTF8 decoding applies
ptrtoTypeRef = getCharTypeRef(1); // to pointer to char
else if (ptrto instanceof AbstractStringDataType) {
if ((ptrto instanceof StringDataType) ||
(type instanceof TerminatedStringDataType)) { // Convert pointer to string
ptrtoTypeRef = getCharTypeRef(dataOrganization.getCharSize()); // to pointer to char
}
else if (ptrto instanceof StringUTF8DataType) { // Convert pointer to string
// TODO: Need to ensure that UTF8 decoding applies
ptrtoTypeRef = getCharTypeRef(1); // to pointer to char
}
else if ((ptrto instanceof UnicodeDataType) ||
(ptrto instanceof TerminatedUnicodeDataType)) {
ptrtoTypeRef = getCharTypeRef(2);
}
else if ((ptrto instanceof Unicode32DataType) ||
(ptrto instanceof TerminatedUnicode32DataType)) {
ptrtoTypeRef = getCharTypeRef(4);
}
else {
ptrtoTypeRef = new StringBuilder();
ptrtoTypeRef.append("<type");
appendNameIdAttributes(ptrtoTypeRef, ptrto);
appendOpaqueString(ptrtoTypeRef, ptrto, 16384);
ptrtoTypeRef.append("</type>\n");
}
}
else if (ptrto instanceof FunctionDefinition) {
// FunctionDefinition may have size of -1, do not translate to undefined
ptrtoTypeRef = buildTypeRef(ptrto, ptrto.getLength());
}
else if ((ptrto instanceof UnicodeDataType) ||
(ptrto instanceof TerminatedUnicodeDataType)) {
ptrtoTypeRef = getCharTypeRef(2);
}
else if ((ptrto instanceof Unicode32DataType) ||
(ptrto instanceof TerminatedUnicode32DataType)) {
ptrtoTypeRef = getCharTypeRef(4);
}
else if (ptrto.getLength() < 0 && !(ptrto instanceof FunctionDefinition)) {
ptrtoTypeRef = buildTypeRef(Undefined1DataType.dataType, 1);
}
@ -373,6 +413,12 @@ public class PcodeDataTypeManager {
resBuf.append(ptrtoTypeRef);
}
else if (type instanceof Array) {
if (origType == type) {
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
}
else {
appendNameIdAttributes(resBuf, origType);
}
int sz = type.getLength();
if (sz == 0) {
sz = size;
@ -386,6 +432,7 @@ public class PcodeDataTypeManager {
buildTypeRef(((Array) type).getDataType(), ((Array) type).getElementLength()));
}
else if (type instanceof Structure) {
appendNameIdAttributes(resBuf, origType);
// if size is 0, insert an Undefined4 component
//
int sz = type.getLength();
@ -417,6 +464,7 @@ public class PcodeDataTypeManager {
// TODO: trailing flexible array component not yet supported
}
else if (type instanceof Enum) {
appendNameIdAttributes(resBuf, origType);
Enum enumDt = (Enum) type;
long[] keys = enumDt.getValues();
String metatype = "uint";
@ -438,6 +486,7 @@ public class PcodeDataTypeManager {
}
}
else if (type instanceof CharDataType) {
appendNameIdAttributes(resBuf, origType);
boolean signed = ((CharDataType) type).isSigned();
int sz = type.getLength();
if (sz <= 0) {
@ -455,44 +504,57 @@ public class PcodeDataTypeManager {
}
else if (type instanceof WideCharDataType || type instanceof WideChar16DataType ||
type instanceof WideChar32DataType) {
appendNameIdAttributes(resBuf, origType);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "int");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength());
SpecXmlUtils.encodeBooleanAttribute(resBuf, "utf", true);
resBuf.append('>');
}
else if ((type instanceof StringDataType) || (type instanceof TerminatedStringDataType)) {
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size);
resBuf.append('>');
resBuf.append(getCharTypeRef(dataOrganization.getCharSize()));
}
else if (type instanceof StringUTF8DataType) {
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size);
resBuf.append('>');
resBuf.append(getCharTypeRef(1)); // TODO: Need to ensure that UTF8 decoding applies
}
else if ((type instanceof UnicodeDataType) || (type instanceof TerminatedUnicodeDataType)) {
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 2);
resBuf.append('>');
resBuf.append(getCharTypeRef(2));
}
else if ((type instanceof Unicode32DataType) ||
(type instanceof TerminatedUnicode32DataType)) {
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 4);
resBuf.append('>');
resBuf.append(getCharTypeRef(4));
else if (type instanceof AbstractStringDataType) {
if ((type instanceof StringDataType) || (type instanceof TerminatedStringDataType)) {
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size);
resBuf.append('>');
resBuf.append(getCharTypeRef(dataOrganization.getCharSize()));
}
else if (type instanceof StringUTF8DataType) {
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size);
resBuf.append('>');
resBuf.append(getCharTypeRef(1)); // TODO: Need to ensure that UTF8 decoding applies
}
else if ((type instanceof UnicodeDataType) ||
(type instanceof TerminatedUnicodeDataType)) {
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 2);
resBuf.append('>');
resBuf.append(getCharTypeRef(2));
}
else if ((type instanceof Unicode32DataType) ||
(type instanceof TerminatedUnicode32DataType)) {
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 4);
resBuf.append('>');
resBuf.append(getCharTypeRef(4));
}
else {
appendNameIdAttributes(resBuf, type);
appendOpaqueString(resBuf, type, size);
}
}
else if (type instanceof FunctionDefinition) {
if (size <= 0) {
size = 1;
}
appendNameIdAttributes(resBuf, origType);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "code");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", 1); // Force size of 1
resBuf.append('>');
@ -502,6 +564,7 @@ public class PcodeDataTypeManager {
fproto.buildPrototypeXML(resBuf, this);
}
else if (type instanceof BooleanDataType) {
appendNameIdAttributes(resBuf, origType);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "bool");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength());
resBuf.append('>');
@ -512,11 +575,13 @@ public class PcodeDataTypeManager {
if (sz <= 0) {
sz = size;
}
appendNameIdAttributes(resBuf, origType);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", signed ? "int" : "uint");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz);
resBuf.append('>');
}
else if (type instanceof AbstractFloatDataType) {
appendNameIdAttributes(resBuf, origType);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "float");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength());
resBuf.append('>');
@ -527,11 +592,13 @@ public class PcodeDataTypeManager {
sz = size;
}
if (sz < 16) {
appendNameIdAttributes(resBuf, origType);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "unknown");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz);
resBuf.append('>');
}
else {
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", sz);
@ -542,6 +609,20 @@ public class PcodeDataTypeManager {
return resBuf.toString();
}
private void appendNameIdAttributes(StringBuilder resBuf, DataType type) {
if (type instanceof BuiltIn) {
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name",
((BuiltIn) type).getDecompilerDisplayName(displayLanguage));
}
else {
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", type.getName());
long id = progDataTypes.getID(type);
if (id > 0) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", id);
}
}
}
/**
* Build an XML document string representing the type information for a data type
*
@ -559,23 +640,6 @@ public class PcodeDataTypeManager {
return resBuf.append("<void/>");
}
resBuf.append("<type");
if ((type instanceof Pointer) || (type instanceof Array) ||
(!(type instanceof FunctionDefinition) && type.getLength() <= 0)) {
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
}
else {
if (type instanceof BuiltIn) {
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name",
((BuiltIn) type).getDecompilerDisplayName(displayLanguage));
}
else {
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", type.getName());
long id = progDataTypes.getID(type);
if (id > 0) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", id);
}
}
}
resBuf.append(buildTypeInternal(type, size));
resBuf.append("</type>");
return resBuf;