Wip new dtw
This commit is contained in:
parent
55438d7380
commit
31ee70e8c0
5424
game_re/gh_types.h
5424
game_re/gh_types.h
File diff suppressed because it is too large
Load Diff
|
@ -19,6 +19,9 @@ typedef uint32_t undefined4;
|
|||
typedef uint16_t undefined2;
|
||||
typedef uint16_t word;
|
||||
typedef uint32_t dword;
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
struct undefined3 {
|
||||
uint8_t _0;
|
||||
uint8_t _1;
|
||||
|
|
|
@ -8,14 +8,7 @@ import ghidra.util.exception.CancelledException;
|
|||
import ghidra.util.task.TaskMonitor;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class DataTypeWriter {
|
||||
public HashSet<String> blacklistedTypes;
|
||||
|
@ -25,14 +18,26 @@ public class DataTypeWriter {
|
|||
private static String[] INTEGRAL_MODIFIERS = new String[] { "signed", "unsigned", "const", "static", "volatile",
|
||||
"mutable" };
|
||||
private static String EOL = System.getProperty("line.separator");
|
||||
private Set<DataType> resolved;
|
||||
private Map<String, DataType> resolvedTypeMap;
|
||||
|
||||
private Writer writer;
|
||||
private DataTypeManager dtm;
|
||||
private DataOrganization dataOrganization;
|
||||
private AnnotationHandler annotator;
|
||||
private boolean cppStyleComments;
|
||||
|
||||
// Block represents a single data type declaration with its dependencies
|
||||
private static class Block {
|
||||
final DataType dataType;
|
||||
final String code;
|
||||
final Set<String> dependencies;
|
||||
|
||||
Block(DataType dataType, String code, Set<String> dependencies) {
|
||||
this.dataType = dataType;
|
||||
this.code = code;
|
||||
this.dependencies = new HashSet<>(dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
public DataTypeWriter(DataTypeManager dtm, Writer writer) throws IOException {
|
||||
this(dtm, writer, new DefaultAnnotationHandler());
|
||||
}
|
||||
|
@ -48,8 +53,6 @@ public class DataTypeWriter {
|
|||
public DataTypeWriter(DataTypeManager dtm, Writer writer, AnnotationHandler annotator, boolean cppStyleComments)
|
||||
throws IOException {
|
||||
this.blacklistedTypes = new HashSet<>();
|
||||
this.resolved = new HashSet();
|
||||
this.resolvedTypeMap = new HashMap();
|
||||
this.cppStyleComments = false;
|
||||
this.dtm = dtm;
|
||||
if (dtm != null) {
|
||||
|
@ -63,9 +66,6 @@ public class DataTypeWriter {
|
|||
this.writer = writer;
|
||||
this.annotator = annotator;
|
||||
this.cppStyleComments = cppStyleComments;
|
||||
if (dtm != null) {
|
||||
// this.writeBuiltInDeclarations(dtm);
|
||||
}
|
||||
}
|
||||
|
||||
private String comment(String text) {
|
||||
|
@ -95,23 +95,10 @@ public class DataTypeWriter {
|
|||
|
||||
this.write(subCategory, monitor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void write(DataType[] dataTypes, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
monitor.initialize((long) dataTypes.length);
|
||||
int cnt = 0;
|
||||
DataType[] var4 = dataTypes;
|
||||
int var5 = dataTypes.length;
|
||||
|
||||
for (int var6 = 0; var6 < var5; ++var6) {
|
||||
DataType dataType = var4[var6];
|
||||
monitor.checkCancelled();
|
||||
this.write(dataType, monitor);
|
||||
++cnt;
|
||||
monitor.setProgress((long) cnt);
|
||||
}
|
||||
|
||||
write(Arrays.asList(dataTypes), monitor);
|
||||
}
|
||||
|
||||
public void write(List<DataType> dataTypes, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
|
@ -120,596 +107,374 @@ public class DataTypeWriter {
|
|||
|
||||
public void write(List<DataType> dataTypes, TaskMonitor monitor, boolean throwExceptionOnInvalidType)
|
||||
throws IOException, CancelledException {
|
||||
// Sort types to handle dependencies
|
||||
List<DataType> sortedTypes = sortTypesByDependencies(dataTypes);
|
||||
monitor.initialize((long) dataTypes.size());
|
||||
|
||||
// Step 1: Create blocks for each data type
|
||||
Map<String, Block> blocks = new HashMap<>();
|
||||
|
||||
monitor.initialize((long) sortedTypes.size());
|
||||
int cnt = 0;
|
||||
|
||||
for (DataType dataType : sortedTypes) {
|
||||
for (DataType dataType : dataTypes) {
|
||||
monitor.checkCancelled();
|
||||
this.writeType(dataType, monitor, throwExceptionOnInvalidType);
|
||||
|
||||
if (dataType == null || blacklistedTypes.contains(dataType.getDisplayName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
Block block = createBlock(dataType);
|
||||
if (block != null) {
|
||||
blocks.put(dataType.getDisplayName(), block);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (throwExceptionOnInvalidType) {
|
||||
throw new IOException("Failed to process data type: " + dataType.getDisplayName(), e);
|
||||
}
|
||||
Msg.error(this, "Failed to process data type: " + dataType.getDisplayName(), e);
|
||||
}
|
||||
|
||||
++cnt;
|
||||
monitor.setProgress((long) cnt);
|
||||
}
|
||||
|
||||
// Step 2: Topological sort and write
|
||||
List<Block> sortedBlocks = topologicalSort(blocks);
|
||||
for (Block block : sortedBlocks) {
|
||||
writer.write(block.code);
|
||||
writer.write(EOL);
|
||||
}
|
||||
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
private List<DataType> sortTypesByDependencies(List<DataType> dataTypes) {
|
||||
// Simple dependency sorting - write forward declarations for composites first,
|
||||
// then non-composites, then composite bodies
|
||||
List<DataType> forwardDeclarations = new ArrayList<>();
|
||||
List<DataType> nonComposites = new ArrayList<>();
|
||||
List<DataType> composites = new ArrayList<>();
|
||||
private Block createBlock(DataType dt) throws IOException {
|
||||
if (dt instanceof FunctionDefinition || dt instanceof FactoryDataType) {
|
||||
return null; // Skip these types
|
||||
}
|
||||
|
||||
for (DataType dt : dataTypes) {
|
||||
if (dt instanceof Structure || dt instanceof Union) {
|
||||
composites.add(dt);
|
||||
} else {
|
||||
nonComposites.add(dt);
|
||||
dt = dt.clone(this.dtm);
|
||||
Set<String> dependencies = new HashSet<>();
|
||||
StringBuilder code = new StringBuilder();
|
||||
|
||||
if (dt.equals(DataType.DEFAULT)) {
|
||||
code.append("typedef unsigned char ").append(DataType.DEFAULT.getName()).append(";");
|
||||
} else if (dt instanceof Dynamic) {
|
||||
// Handle dynamic types
|
||||
Dynamic dynamicType = (Dynamic) dt;
|
||||
DataType baseDt = dynamicType.getReplacementBaseType();
|
||||
if (baseDt != null) {
|
||||
dependencies.add(baseDt.getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
List<DataType> result = new ArrayList<>();
|
||||
// First add forward declarations for all composites
|
||||
result.addAll(composites);
|
||||
// Then add non-composites
|
||||
result.addAll(nonComposites);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void write(DataType dt, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
this.writeType(dt, monitor, true);
|
||||
}
|
||||
|
||||
void write(DataType dt, TaskMonitor monitor, boolean throwExceptionOnInvalidType)
|
||||
throws IOException, CancelledException {
|
||||
this.writeType(dt, monitor, throwExceptionOnInvalidType);
|
||||
}
|
||||
|
||||
private void writeType(DataType dt, TaskMonitor monitor, boolean throwExceptionOnInvalidType)
|
||||
throws IOException, CancelledException {
|
||||
if (dt == null || blacklistedTypes.contains(dt.getDisplayName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dt instanceof FunctionDefinition) {
|
||||
return; // Skip function definitions
|
||||
}
|
||||
|
||||
if (dt instanceof FactoryDataType) {
|
||||
IllegalArgumentException iae = new IllegalArgumentException("Factory data types may not be written");
|
||||
if (throwExceptionOnInvalidType) {
|
||||
throw iae;
|
||||
}
|
||||
Msg.error(this, "Factory data types may not be written - type: " + dt);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle pointer/array types by just getting their base type for dependency checking
|
||||
if (dt instanceof Pointer || dt instanceof Array || dt instanceof BitFieldDataType) {
|
||||
// Don't auto-discover dependencies, just write the type as-is
|
||||
code.append(comment("Dynamic type: " + dt.getDisplayName()));
|
||||
} else if (dt instanceof Structure) {
|
||||
writeStructureBlock((Structure) dt, code, dependencies);
|
||||
} else if (dt instanceof Union) {
|
||||
writeUnionBlock((Union) dt, code, dependencies);
|
||||
} else if (dt instanceof Enum) {
|
||||
writeEnumBlock((Enum) dt, code, dependencies);
|
||||
} else if (dt instanceof TypeDef) {
|
||||
writeTypeDefBlock((TypeDef) dt, code, dependencies);
|
||||
} else if (dt instanceof BuiltInDataType) {
|
||||
writeBuiltInBlock((BuiltInDataType) dt, code, dependencies);
|
||||
} else {
|
||||
dt = dt.clone(this.dtm);
|
||||
code.append(comment("Unable to write datatype. Type unrecognized: " + dt.getClass()));
|
||||
}
|
||||
|
||||
if (this.resolved.contains(dt)) {
|
||||
return; // Already written
|
||||
}
|
||||
|
||||
this.resolved.add(dt);
|
||||
DataType resolvedType = this.resolvedTypeMap.get(dt.getName());
|
||||
if (resolvedType != null && !resolvedType.isEquivalent(dt)) {
|
||||
// Handle name conflicts
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(this.comment("WARNING! conflicting data type names: " + dt.getPathName() + " - " + resolvedType.getPathName()));
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(EOL);
|
||||
} else {
|
||||
this.resolvedTypeMap.put(dt.getName(), dt);
|
||||
|
||||
if (dt.equals(DataType.DEFAULT)) {
|
||||
this.writer.write("typedef unsigned char " + DataType.DEFAULT.getName() + ";");
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(EOL);
|
||||
} else if (dt instanceof Dynamic) {
|
||||
this.writeDynamicBuiltIn((Dynamic) dt, monitor);
|
||||
} else if (dt instanceof Structure) {
|
||||
this.writeStructure((Structure) dt, monitor);
|
||||
} else if (dt instanceof Union) {
|
||||
this.writeUnion((Union) dt, monitor);
|
||||
} else if (dt instanceof Enum) {
|
||||
this.writeEnum((Enum) dt, monitor);
|
||||
} else if (dt instanceof TypeDef) {
|
||||
this.writeTypeDef((TypeDef) dt, monitor);
|
||||
} else if (dt instanceof BuiltInDataType) {
|
||||
this.writeBuiltIn((BuiltInDataType) dt, monitor);
|
||||
} else if (!(dt instanceof BitFieldDataType)) {
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(this.comment("Unable to write datatype. Type unrecognized: " + dt.getClass()));
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(EOL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeStructure(Structure struct, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
// Write forward declaration first
|
||||
this.writer.write("typedef struct " + struct.getDisplayName() + " " + struct.getDisplayName() + ", *P" + struct.getDisplayName() + ";");
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(EOL);
|
||||
|
||||
// Then write the body
|
||||
this.writeCompositeBody(struct, monitor);
|
||||
return new Block(dt, code.toString(), dependencies);
|
||||
}
|
||||
|
||||
private void writeUnion(Union union, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
// Write forward declaration first
|
||||
this.writer.write("typedef union " + union.getDisplayName() + " " + union.getDisplayName() + ", *P" + union.getDisplayName() + ";");
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(EOL);
|
||||
private void writeStructureBlock(Structure struct, StringBuilder code, Set<String> dependencies) {
|
||||
String structName = struct.getDisplayName();
|
||||
|
||||
// Then write the body
|
||||
this.writeCompositeBody(union, monitor);
|
||||
}
|
||||
|
||||
private void writeCompositeBody(Composite composite, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
String compositeType = composite instanceof Structure ? "struct" : "union";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(compositeType + " " + composite.getDisplayName() + " {");
|
||||
String descrip = composite.getDescription();
|
||||
// Struct definition
|
||||
code.append("struct ").append(structName).append(" {");
|
||||
String descrip = struct.getDescription();
|
||||
if (descrip != null && descrip.length() > 0) {
|
||||
String var10001 = this.comment(descrip);
|
||||
sb.append(" " + var10001);
|
||||
code.append(" ").append(comment(descrip));
|
||||
}
|
||||
|
||||
sb.append(EOL);
|
||||
DataTypeComponent[] var6 = composite.getComponents();
|
||||
int var7 = var6.length;
|
||||
|
||||
for (int var8 = 0; var8 < var7; ++var8) {
|
||||
DataTypeComponent component = var6[var8];
|
||||
monitor.checkCancelled();
|
||||
this.writeComponent(component, composite, sb, monitor);
|
||||
code.append(EOL);
|
||||
|
||||
// Process components
|
||||
for (DataTypeComponent component : struct.getComponents()) {
|
||||
writeComponentBlock(component, struct, code, dependencies);
|
||||
}
|
||||
|
||||
sb.append(this.annotator.getSuffix(composite, (DataTypeComponent) null));
|
||||
sb.append("};");
|
||||
this.writer.write(sb.toString());
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(EOL);
|
||||
|
||||
code.append(annotator.getSuffix(struct, null));
|
||||
code.append("};");
|
||||
}
|
||||
|
||||
private void writeComponent(DataTypeComponent component, Composite composite, StringBuilder sb, TaskMonitor monitor)
|
||||
throws IOException, CancelledException {
|
||||
sb.append(" ");
|
||||
sb.append(this.annotator.getPrefix(composite, component));
|
||||
private void writeUnionBlock(Union union, StringBuilder code, Set<String> dependencies) {
|
||||
String unionName = union.getDisplayName();
|
||||
|
||||
// Forward declaration
|
||||
code.append("typedef union ").append(unionName).append(" ").append(unionName)
|
||||
.append(", *P").append(unionName).append(";").append(EOL);
|
||||
|
||||
// Union definition
|
||||
code.append("union ").append(unionName).append(" {");
|
||||
String descrip = union.getDescription();
|
||||
if (descrip != null && descrip.length() > 0) {
|
||||
code.append(" ").append(comment(descrip));
|
||||
}
|
||||
code.append(EOL);
|
||||
|
||||
// Process components
|
||||
for (DataTypeComponent component : union.getComponents()) {
|
||||
writeComponentBlock(component, union, code, dependencies);
|
||||
}
|
||||
|
||||
code.append(annotator.getSuffix(union, null));
|
||||
code.append("};");
|
||||
}
|
||||
|
||||
private void writeComponentBlock(DataTypeComponent component, Composite composite, StringBuilder code, Set<String> dependencies) {
|
||||
code.append(" ");
|
||||
code.append(annotator.getPrefix(composite, component));
|
||||
|
||||
String fieldName = component.getFieldName();
|
||||
if (fieldName == null || fieldName.length() == 0) {
|
||||
fieldName = component.getDefaultFieldName();
|
||||
}
|
||||
|
||||
|
||||
DataType componentDataType = component.getDataType();
|
||||
sb.append(this.getTypeDeclaration(fieldName, componentDataType, component.getLength(), false, monitor));
|
||||
sb.append(";");
|
||||
sb.append(this.annotator.getSuffix(composite, component));
|
||||
|
||||
// Add dependency only if it's not a pointer (pointers can be forward declared)
|
||||
if (!isPointerType(componentDataType)) {
|
||||
DataType baseType = getBaseDataType(componentDataType);
|
||||
if (baseType != null && !isBuiltInType(baseType)) {
|
||||
dependencies.add(baseType.getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
code.append(getTypeDeclaration(fieldName, componentDataType, component.getLength()));
|
||||
code.append(";");
|
||||
code.append(annotator.getSuffix(composite, component));
|
||||
|
||||
String comment = component.getComment();
|
||||
if (comment != null && comment.length() > 0) {
|
||||
String var10001 = this.comment(comment);
|
||||
sb.append(" " + var10001);
|
||||
code.append(" ").append(comment(comment));
|
||||
}
|
||||
|
||||
sb.append(EOL);
|
||||
code.append(EOL);
|
||||
}
|
||||
|
||||
private String getTypeDeclaration(String name, DataType dataType, int instanceLength, boolean writeEnabled,
|
||||
TaskMonitor monitor) throws IOException, CancelledException {
|
||||
private void writeEnumBlock(Enum enumm, StringBuilder code, Set<String> dependencies) {
|
||||
String enumName = enumm.getDisplayName();
|
||||
|
||||
if (enumName.startsWith("define_") && enumName.length() > 7 && enumm.getCount() == 1) {
|
||||
long val = enumm.getValues()[0];
|
||||
code.append("#define ").append(enumName.substring(7)).append(" ").append(Long.toString(val));
|
||||
} else {
|
||||
code.append("enum ").append(enumName).append(" {");
|
||||
String description = enumm.getDescription();
|
||||
if (description != null && description.length() != 0) {
|
||||
code.append(" ").append(comment(description));
|
||||
}
|
||||
code.append(EOL);
|
||||
|
||||
String[] names = enumm.getNames();
|
||||
for (int j = 0; j < names.length; ++j) {
|
||||
code.append(" ");
|
||||
code.append(annotator.getPrefix(enumm, names[j]));
|
||||
code.append(names[j]);
|
||||
code.append("=");
|
||||
code.append(Long.toString(enumm.getValue(names[j])));
|
||||
String comment = enumm.getComment(names[j]);
|
||||
if (!comment.isBlank()) {
|
||||
code.append(" ").append(comment(comment));
|
||||
}
|
||||
code.append(annotator.getSuffix(enumm, names[j]));
|
||||
if (j < names.length - 1) {
|
||||
code.append(",");
|
||||
}
|
||||
code.append(EOL);
|
||||
}
|
||||
code.append("};");
|
||||
}
|
||||
}
|
||||
|
||||
private void writeTypeDefBlock(TypeDef typeDef, StringBuilder code, Set<String> dependencies) {
|
||||
String typedefName = typeDef.getDisplayName();
|
||||
DataType dataType = typeDef.getDataType();
|
||||
String dataTypeName = dataType.getDisplayName();
|
||||
|
||||
if (!isIntegral(typedefName, dataTypeName)) {
|
||||
DataType baseType = typeDef.getBaseDataType();
|
||||
|
||||
// Add dependency only if it's not a pointer
|
||||
if (!isPointerType(dataType)) {
|
||||
DataType depType = getBaseDataType(dataType);
|
||||
if (depType != null && !isBuiltInType(depType)) {
|
||||
dependencies.add(depType.getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
String typedefString = getTypeDeclaration(typedefName, dataType, -1);
|
||||
code.append("typedef ").append(typedefString).append(";");
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBuiltInBlock(BuiltInDataType dt, StringBuilder code, Set<String> dependencies) {
|
||||
String declaration = dt.getCTypeDeclaration(this.dataOrganization);
|
||||
if (declaration != null && !dt.getDisplayName().equals("bool")) {
|
||||
code.append(declaration);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPointerType(DataType dt) {
|
||||
return dt instanceof Pointer;
|
||||
}
|
||||
|
||||
private boolean isBuiltInType(DataType dt) {
|
||||
return dt instanceof BuiltInDataType ||
|
||||
dt.getDisplayName().equals("void") ||
|
||||
dt.getDisplayName().equals("char") ||
|
||||
dt.getDisplayName().equals("int") ||
|
||||
dt.getDisplayName().equals("short") ||
|
||||
dt.getDisplayName().equals("long") ||
|
||||
dt.getDisplayName().equals("float") ||
|
||||
dt.getDisplayName().equals("double");
|
||||
}
|
||||
|
||||
private DataType getBaseDataType(DataType dt) {
|
||||
while (dt != null) {
|
||||
if (dt instanceof Array) {
|
||||
dt = ((Array) dt).getDataType();
|
||||
} else if (dt instanceof Pointer) {
|
||||
dt = ((Pointer) dt).getDataType();
|
||||
} else if (dt instanceof BitFieldDataType) {
|
||||
dt = ((BitFieldDataType) dt).getBaseDataType();
|
||||
} else if (dt instanceof TypeDef) {
|
||||
dt = ((TypeDef) dt).getBaseDataType();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
private String getTypeDeclaration(String name, DataType dataType, int instanceLength) {
|
||||
if (name == null) {
|
||||
name = "";
|
||||
}
|
||||
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String componentString = null;
|
||||
if (dataType instanceof Dynamic) {
|
||||
// Simplified dynamic handling - just use the display name
|
||||
componentString = dataType.getDisplayName();
|
||||
if (name.length() != 0) {
|
||||
componentString = componentString + " " + name;
|
||||
}
|
||||
sb.append(componentString);
|
||||
|
||||
if (dataType instanceof BitFieldDataType) {
|
||||
BitFieldDataType bfDt = (BitFieldDataType) dataType;
|
||||
name = name + ":" + bfDt.getDeclaredBitSize();
|
||||
dataType = bfDt.getBaseDataType();
|
||||
}
|
||||
|
||||
if (componentString == null) {
|
||||
if (dataType instanceof BitFieldDataType) {
|
||||
BitFieldDataType bfDt = (BitFieldDataType) dataType;
|
||||
name = name + ":" + bfDt.getDeclaredBitSize();
|
||||
dataType = bfDt.getBaseDataType();
|
||||
}
|
||||
|
||||
label44: while (true) {
|
||||
while (!(dataType instanceof Array)) {
|
||||
if (!(dataType instanceof Pointer)) {
|
||||
break label44;
|
||||
}
|
||||
|
||||
Pointer pointer = (Pointer) dataType;
|
||||
DataType elem = pointer.getDataType();
|
||||
if (elem == null) {
|
||||
break label44;
|
||||
}
|
||||
|
||||
name = "*" + name;
|
||||
dataType = elem;
|
||||
if (elem instanceof Array) {
|
||||
name = "(" + name + ")";
|
||||
}
|
||||
}
|
||||
|
||||
Array array = (Array) dataType;
|
||||
name = name + "[" + array.getNumElements() + "]";
|
||||
dataType = array.getDataType();
|
||||
}
|
||||
|
||||
DataType baseDataType = this.getBaseDataType(dataType);
|
||||
if (baseDataType instanceof FunctionDefinition) {
|
||||
componentString = this.getFunctionPointerString((FunctionDefinition) baseDataType, name, dataType, writeEnabled,
|
||||
monitor);
|
||||
} else {
|
||||
String var10000 = this.getDataTypePrefix(dataType);
|
||||
componentString = var10000 + dataType.getDisplayName();
|
||||
if (name.length() != 0) {
|
||||
componentString = componentString + " " + name;
|
||||
}
|
||||
}
|
||||
|
||||
sb.append(componentString);
|
||||
|
||||
// Handle arrays and pointers
|
||||
while (dataType instanceof Array) {
|
||||
Array array = (Array) dataType;
|
||||
name = name + "[" + array.getNumElements() + "]";
|
||||
dataType = array.getDataType();
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
|
||||
while (dataType instanceof Pointer) {
|
||||
Pointer pointer = (Pointer) dataType;
|
||||
DataType elem = pointer.getDataType();
|
||||
if (elem == null) {
|
||||
break;
|
||||
}
|
||||
name = "*" + name;
|
||||
dataType = elem;
|
||||
if (elem instanceof Array) {
|
||||
name = "(" + name + ")";
|
||||
}
|
||||
}
|
||||
|
||||
String prefix = getDataTypePrefix(dataType);
|
||||
String componentString = prefix + dataType.getDisplayName();
|
||||
if (name.length() != 0) {
|
||||
componentString = componentString + " " + name;
|
||||
}
|
||||
|
||||
return componentString;
|
||||
}
|
||||
|
||||
private String getDataTypePrefix(DataType dataType) {
|
||||
dataType = this.getBaseDataType(dataType);
|
||||
dataType = getBaseDataType(dataType);
|
||||
if (dataType instanceof Structure) {
|
||||
return "struct ";
|
||||
} else if (dataType instanceof Union) {
|
||||
return "union ";
|
||||
} else if (dataType instanceof Enum) {
|
||||
return "enum ";
|
||||
} else {
|
||||
return dataType instanceof Enum ? "enum " : "";
|
||||
}
|
||||
}
|
||||
|
||||
private void writeEnum(Enum enumm, TaskMonitor monitor) throws IOException {
|
||||
String enumName = enumm.getDisplayName();
|
||||
Writer var10000;
|
||||
String var10001;
|
||||
if (enumName.startsWith("define_") && enumName.length() > 7 && enumm.getCount() == 1) {
|
||||
long val = enumm.getValues()[0];
|
||||
var10000 = this.writer;
|
||||
var10001 = enumName.substring(7);
|
||||
var10000.append("#define " + var10001 + " " + Long.toString(val));
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(EOL);
|
||||
} else {
|
||||
this.writer.write("enum " + enumName + " {");
|
||||
String description = enumm.getDescription();
|
||||
if (description != null && description.length() != 0) {
|
||||
var10000 = this.writer;
|
||||
var10001 = this.comment(description);
|
||||
var10000.write(" " + var10001);
|
||||
}
|
||||
|
||||
this.writer.write(EOL);
|
||||
String[] names = enumm.getNames();
|
||||
|
||||
for (int j = 0; j < names.length; ++j) {
|
||||
this.writer.write(" ");
|
||||
this.writer.write(this.annotator.getPrefix(enumm, names[j]));
|
||||
this.writer.write(names[j]);
|
||||
this.writer.write("=");
|
||||
this.writer.write(Long.toString(enumm.getValue(names[j])));
|
||||
String comment = enumm.getComment(names[j]);
|
||||
if (!comment.isBlank()) {
|
||||
var10000 = this.writer;
|
||||
var10001 = this.comment(comment);
|
||||
var10000.write(" " + var10001);
|
||||
}
|
||||
|
||||
this.writer.write(this.annotator.getSuffix(enumm, names[j]));
|
||||
if (j < names.length - 1) {
|
||||
this.writer.write(",");
|
||||
}
|
||||
|
||||
this.writer.write(EOL);
|
||||
}
|
||||
|
||||
this.writer.write("};");
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(EOL);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeTypeDef(TypeDef typeDef, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
String typedefName = typeDef.getDisplayName();
|
||||
DataType dataType = typeDef.getDataType();
|
||||
String dataTypeName = dataType.getDisplayName();
|
||||
if (!this.isIntegral(typedefName, dataTypeName)) {
|
||||
DataType baseType = typeDef.getBaseDataType();
|
||||
|
||||
label125: {
|
||||
try {
|
||||
if (!(baseType instanceof Composite) && !(baseType instanceof Enum)) {
|
||||
if (!(baseType instanceof Pointer) || !typedefName.startsWith("P")) {
|
||||
break label125;
|
||||
}
|
||||
|
||||
DataType dt = ((Pointer) baseType).getDataType();
|
||||
if (dt instanceof TypeDef) {
|
||||
dt = ((TypeDef) dt).getBaseDataType();
|
||||
}
|
||||
|
||||
if (!(dt instanceof Composite) || !dt.getName().equals(typedefName.substring(1))) {
|
||||
break label125;
|
||||
}
|
||||
|
||||
this.resolvedTypeMap.remove(typedefName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!typedefName.equals(baseType.getName())) {
|
||||
break label125;
|
||||
}
|
||||
|
||||
this.resolvedTypeMap.remove(typedefName);
|
||||
} finally {
|
||||
// Removed auto-discovery - don't write the dataType automatically
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Removed deferred writing call - we only write what's explicitly passed
|
||||
|
||||
String typedefString = this.getTypeDeclaration(typedefName, dataType, -1, true, monitor);
|
||||
this.writer.write("typedef " + typedefString + ";");
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(EOL);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isIntegral(String typedefName, String basetypeName) {
|
||||
String[] var3 = INTEGRAL_TYPES;
|
||||
int var4 = var3.length;
|
||||
|
||||
int var5;
|
||||
for (var5 = 0; var5 < var4; ++var5) {
|
||||
String type = var3[var5];
|
||||
for (String type : INTEGRAL_TYPES) {
|
||||
if (typedefName.equals(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean endsWithIntegralType = false;
|
||||
String[] var10 = INTEGRAL_TYPES;
|
||||
var5 = var10.length;
|
||||
|
||||
int var13;
|
||||
for (var13 = 0; var13 < var5; ++var13) {
|
||||
String type = var10[var13];
|
||||
for (String type : INTEGRAL_TYPES) {
|
||||
if (typedefName.endsWith(" " + type)) {
|
||||
endsWithIntegralType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean containsIntegralModifier = false;
|
||||
String[] var12 = INTEGRAL_MODIFIERS;
|
||||
var13 = var12.length;
|
||||
|
||||
for (int var14 = 0; var14 < var13; ++var14) {
|
||||
String modifier = var12[var14];
|
||||
|
||||
for (String modifier : INTEGRAL_MODIFIERS) {
|
||||
if (typedefName.indexOf(modifier + " ") >= 0 || typedefName.indexOf(" " + modifier) >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (endsWithIntegralType && containsIntegralModifier) {
|
||||
|
||||
if (endsWithIntegralType) {
|
||||
return true;
|
||||
} else if (typedefName.endsWith(" " + basetypeName)) {
|
||||
return containsIntegralModifier;
|
||||
return false; // Let it through as a regular typedef
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDynamicBuiltIn(Dynamic dt, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
// Simplified - don't auto-discover replacement types
|
||||
// Just write a comment about the dynamic type
|
||||
this.writer.write(this.comment("Dynamic type: " + dt.getDisplayName()));
|
||||
this.writer.write(EOL);
|
||||
this.writer.write(EOL);
|
||||
}
|
||||
|
||||
private void writeBuiltIn(BuiltInDataType dt, TaskMonitor monitor) throws IOException {
|
||||
String declaration = dt.getCTypeDeclaration(this.dataOrganization);
|
||||
if (declaration != null) {
|
||||
if (dt.getDisplayName() == "bool")
|
||||
return;
|
||||
this.writer.write(declaration);
|
||||
this.writer.write(EOL);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBuiltInDeclarations(DataTypeManager manager) throws IOException {
|
||||
try {
|
||||
this.write(DataType.DEFAULT, TaskMonitor.DUMMY);
|
||||
SourceArchive builtInArchive = manager.getSourceArchive(DataTypeManager.BUILT_IN_ARCHIVE_UNIVERSAL_ID);
|
||||
if (builtInArchive == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Iterator var3 = manager.getDataTypes(builtInArchive).iterator();
|
||||
|
||||
while (var3.hasNext()) {
|
||||
DataType dt = (DataType) var3.next();
|
||||
if (!(dt instanceof Pointer) && !(dt instanceof FactoryDataType) && !(dt instanceof Dynamic)) {
|
||||
this.write(dt, TaskMonitor.DUMMY);
|
||||
}
|
||||
}
|
||||
} catch (CancelledException var5) {
|
||||
}
|
||||
|
||||
this.writer.flush();
|
||||
}
|
||||
|
||||
private static String getArrayDimensions(Array arrayDt) {
|
||||
String dimensionString = "[" + arrayDt.getNumElements() + "]";
|
||||
DataType dataType = arrayDt.getDataType();
|
||||
if (dataType instanceof Array) {
|
||||
dimensionString = dimensionString + getArrayDimensions((Array) dataType);
|
||||
}
|
||||
|
||||
return dimensionString;
|
||||
}
|
||||
|
||||
private DataType getBaseDataType(DataType dt) {
|
||||
while (true) {
|
||||
if (dt != null) {
|
||||
if (dt instanceof Array) {
|
||||
Array array = (Array) dt;
|
||||
dt = array.getDataType();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dt instanceof Pointer) {
|
||||
Pointer pointer = (Pointer) dt;
|
||||
dt = pointer.getDataType();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dt instanceof BitFieldDataType) {
|
||||
BitFieldDataType bitfieldDt = (BitFieldDataType) dt;
|
||||
dt = bitfieldDt.getBaseDataType();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return dt;
|
||||
}
|
||||
}
|
||||
|
||||
private DataType getArrayBaseType(Array arrayDt) {
|
||||
DataType dataType;
|
||||
for (dataType = arrayDt.getDataType(); dataType instanceof Array; dataType = ((Array) dataType).getDataType()) {
|
||||
}
|
||||
|
||||
return dataType;
|
||||
}
|
||||
|
||||
private DataType getPointerBaseDataType(Pointer p) {
|
||||
DataType dt;
|
||||
for (dt = p.getDataType(); dt instanceof Pointer; dt = ((Pointer) dt).getDataType()) {
|
||||
}
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
private int getPointerDepth(Pointer p) {
|
||||
int depth = 1;
|
||||
|
||||
for (DataType dt = p.getDataType(); dt instanceof Pointer; dt = ((Pointer) dt).getDataType()) {
|
||||
++depth;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
private String getFunctionPointerString(FunctionDefinition fd, String name, DataType functionPointerArrayType,
|
||||
boolean writeEnabled, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
DataType originalType = functionPointerArrayType;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
DataType returnType = fd.getReturnType();
|
||||
if (writeEnabled) {
|
||||
this.write(returnType, monitor);
|
||||
}
|
||||
|
||||
sb.append("(");
|
||||
String arrayDecorations = "";
|
||||
if (functionPointerArrayType instanceof Array a) {
|
||||
functionPointerArrayType = this.getArrayBaseType(a);
|
||||
arrayDecorations = getArrayDimensions(a);
|
||||
}
|
||||
|
||||
if (functionPointerArrayType instanceof Pointer p) {
|
||||
for (int i = 0; i < this.getPointerDepth(p); ++i) {
|
||||
sb.append('*');
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
sb.append(' ');
|
||||
}
|
||||
|
||||
functionPointerArrayType = this.getPointerBaseDataType(p);
|
||||
}
|
||||
|
||||
if (!(functionPointerArrayType instanceof FunctionDefinition)) {
|
||||
this.writer.append(this
|
||||
.comment("Attempting output of invalid function pointer type declaration: " + originalType.getDisplayName()));
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
sb.append(name);
|
||||
}
|
||||
|
||||
if (arrayDecorations.length() != 0) {
|
||||
sb.append(arrayDecorations);
|
||||
}
|
||||
|
||||
sb.append(")");
|
||||
sb.append(this.getParameterListString(fd, false, writeEnabled, monitor));
|
||||
DataType baseReturnType = this.getBaseDataType(returnType);
|
||||
if (baseReturnType instanceof FunctionDefinition) {
|
||||
return this.getFunctionPointerString((FunctionDefinition) baseReturnType, sb.toString(), returnType, writeEnabled,
|
||||
monitor);
|
||||
} else {
|
||||
String var10000 = returnType.getDisplayName();
|
||||
return var10000 + " " + sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private String getParameterListString(FunctionDefinition fd, boolean includeParamNames, boolean writeEnabled,
|
||||
TaskMonitor monitor) throws IOException, CancelledException {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("(");
|
||||
boolean hasVarArgs = fd.hasVarArgs();
|
||||
ParameterDefinition[] parameters = fd.getArguments();
|
||||
int n = parameters.length;
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
ParameterDefinition param = parameters[i];
|
||||
String paramName = includeParamNames ? param.getName() : null;
|
||||
DataType dataType = param.getDataType();
|
||||
if (writeEnabled) {
|
||||
this.write(dataType, monitor);
|
||||
}
|
||||
|
||||
String argument = this.getTypeDeclaration(paramName, dataType, param.getLength(), writeEnabled, monitor);
|
||||
buf.append(argument);
|
||||
if (i < n - 1 || hasVarArgs) {
|
||||
buf.append(", ");
|
||||
private List<Block> topologicalSort(Map<String, Block> blocks) {
|
||||
List<Block> result = new ArrayList<>();
|
||||
Set<String> visited = new HashSet<>();
|
||||
Set<String> visiting = new HashSet<>();
|
||||
|
||||
for (Block block : blocks.values()) {
|
||||
if (!visited.contains(block.dataType.getDisplayName())) {
|
||||
topologicalSortVisit(block, blocks, visited, visiting, result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (hasVarArgs) {
|
||||
buf.append("...");
|
||||
private void topologicalSortVisit(Block block, Map<String, Block> blocks,
|
||||
Set<String> visited, Set<String> visiting, List<Block> result) {
|
||||
String blockName = block.dataType.getDisplayName();
|
||||
|
||||
if (visiting.contains(blockName)) {
|
||||
// Circular dependency detected, but we'll continue (forward declarations should handle this)
|
||||
return;
|
||||
}
|
||||
|
||||
if (n == 0 && !hasVarArgs) {
|
||||
buf.append(VoidDataType.dataType.getName());
|
||||
|
||||
if (visited.contains(blockName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
buf.append(")");
|
||||
return buf.toString();
|
||||
|
||||
visiting.add(blockName);
|
||||
|
||||
// Visit dependencies first
|
||||
for (String dep : block.dependencies) {
|
||||
Block depBlock = blocks.get(dep);
|
||||
if (depBlock != null) {
|
||||
topologicalSortVisit(depBlock, blocks, visited, visiting, result);
|
||||
}
|
||||
}
|
||||
|
||||
visiting.remove(blockName);
|
||||
visited.add(blockName);
|
||||
result.add(block);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue