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 undefined2;
|
||||||
typedef uint16_t word;
|
typedef uint16_t word;
|
||||||
typedef uint32_t dword;
|
typedef uint32_t dword;
|
||||||
|
typedef unsigned long ulong;
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
|
||||||
struct undefined3 {
|
struct undefined3 {
|
||||||
uint8_t _0;
|
uint8_t _0;
|
||||||
uint8_t _1;
|
uint8_t _1;
|
||||||
|
|
|
@ -8,14 +8,7 @@ import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayDeque;
|
import java.util.*;
|
||||||
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;
|
|
||||||
|
|
||||||
public class DataTypeWriter {
|
public class DataTypeWriter {
|
||||||
public HashSet<String> blacklistedTypes;
|
public HashSet<String> blacklistedTypes;
|
||||||
|
@ -25,14 +18,26 @@ public class DataTypeWriter {
|
||||||
private static String[] INTEGRAL_MODIFIERS = new String[] { "signed", "unsigned", "const", "static", "volatile",
|
private static String[] INTEGRAL_MODIFIERS = new String[] { "signed", "unsigned", "const", "static", "volatile",
|
||||||
"mutable" };
|
"mutable" };
|
||||||
private static String EOL = System.getProperty("line.separator");
|
private static String EOL = System.getProperty("line.separator");
|
||||||
private Set<DataType> resolved;
|
|
||||||
private Map<String, DataType> resolvedTypeMap;
|
|
||||||
private Writer writer;
|
private Writer writer;
|
||||||
private DataTypeManager dtm;
|
private DataTypeManager dtm;
|
||||||
private DataOrganization dataOrganization;
|
private DataOrganization dataOrganization;
|
||||||
private AnnotationHandler annotator;
|
private AnnotationHandler annotator;
|
||||||
private boolean cppStyleComments;
|
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 {
|
public DataTypeWriter(DataTypeManager dtm, Writer writer) throws IOException {
|
||||||
this(dtm, writer, new DefaultAnnotationHandler());
|
this(dtm, writer, new DefaultAnnotationHandler());
|
||||||
}
|
}
|
||||||
|
@ -48,8 +53,6 @@ public class DataTypeWriter {
|
||||||
public DataTypeWriter(DataTypeManager dtm, Writer writer, AnnotationHandler annotator, boolean cppStyleComments)
|
public DataTypeWriter(DataTypeManager dtm, Writer writer, AnnotationHandler annotator, boolean cppStyleComments)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
this.blacklistedTypes = new HashSet<>();
|
this.blacklistedTypes = new HashSet<>();
|
||||||
this.resolved = new HashSet();
|
|
||||||
this.resolvedTypeMap = new HashMap();
|
|
||||||
this.cppStyleComments = false;
|
this.cppStyleComments = false;
|
||||||
this.dtm = dtm;
|
this.dtm = dtm;
|
||||||
if (dtm != null) {
|
if (dtm != null) {
|
||||||
|
@ -63,9 +66,6 @@ public class DataTypeWriter {
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
this.annotator = annotator;
|
this.annotator = annotator;
|
||||||
this.cppStyleComments = cppStyleComments;
|
this.cppStyleComments = cppStyleComments;
|
||||||
if (dtm != null) {
|
|
||||||
// this.writeBuiltInDeclarations(dtm);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String comment(String text) {
|
private String comment(String text) {
|
||||||
|
@ -95,23 +95,10 @@ public class DataTypeWriter {
|
||||||
|
|
||||||
this.write(subCategory, monitor);
|
this.write(subCategory, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(DataType[] dataTypes, TaskMonitor monitor) throws IOException, CancelledException {
|
public void write(DataType[] dataTypes, TaskMonitor monitor) throws IOException, CancelledException {
|
||||||
monitor.initialize((long) dataTypes.length);
|
write(Arrays.asList(dataTypes), monitor);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(List<DataType> dataTypes, TaskMonitor monitor) throws IOException, CancelledException {
|
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)
|
public void write(List<DataType> dataTypes, TaskMonitor monitor, boolean throwExceptionOnInvalidType)
|
||||||
throws IOException, CancelledException {
|
throws IOException, CancelledException {
|
||||||
// Sort types to handle dependencies
|
monitor.initialize((long) dataTypes.size());
|
||||||
List<DataType> sortedTypes = sortTypesByDependencies(dataTypes);
|
|
||||||
|
// Step 1: Create blocks for each data type
|
||||||
|
Map<String, Block> blocks = new HashMap<>();
|
||||||
|
|
||||||
monitor.initialize((long) sortedTypes.size());
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
for (DataType dataType : dataTypes) {
|
||||||
for (DataType dataType : sortedTypes) {
|
|
||||||
monitor.checkCancelled();
|
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;
|
++cnt;
|
||||||
monitor.setProgress((long) 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) {
|
private Block createBlock(DataType dt) throws IOException {
|
||||||
// Simple dependency sorting - write forward declarations for composites first,
|
if (dt instanceof FunctionDefinition || dt instanceof FactoryDataType) {
|
||||||
// then non-composites, then composite bodies
|
return null; // Skip these types
|
||||||
List<DataType> forwardDeclarations = new ArrayList<>();
|
}
|
||||||
List<DataType> nonComposites = new ArrayList<>();
|
|
||||||
List<DataType> composites = new ArrayList<>();
|
|
||||||
|
|
||||||
for (DataType dt : dataTypes) {
|
dt = dt.clone(this.dtm);
|
||||||
if (dt instanceof Structure || dt instanceof Union) {
|
Set<String> dependencies = new HashSet<>();
|
||||||
composites.add(dt);
|
StringBuilder code = new StringBuilder();
|
||||||
} else {
|
|
||||||
nonComposites.add(dt);
|
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());
|
||||||
}
|
}
|
||||||
}
|
code.append(comment("Dynamic type: " + dt.getDisplayName()));
|
||||||
|
} else if (dt instanceof Structure) {
|
||||||
List<DataType> result = new ArrayList<>();
|
writeStructureBlock((Structure) dt, code, dependencies);
|
||||||
// First add forward declarations for all composites
|
} else if (dt instanceof Union) {
|
||||||
result.addAll(composites);
|
writeUnionBlock((Union) dt, code, dependencies);
|
||||||
// Then add non-composites
|
} else if (dt instanceof Enum) {
|
||||||
result.addAll(nonComposites);
|
writeEnumBlock((Enum) dt, code, dependencies);
|
||||||
|
} else if (dt instanceof TypeDef) {
|
||||||
return result;
|
writeTypeDefBlock((TypeDef) dt, code, dependencies);
|
||||||
}
|
} else if (dt instanceof BuiltInDataType) {
|
||||||
|
writeBuiltInBlock((BuiltInDataType) dt, code, dependencies);
|
||||||
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
|
|
||||||
} else {
|
} 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
|
return new Block(dt, code.toString(), dependencies);
|
||||||
this.writeCompositeBody(struct, monitor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeUnion(Union union, TaskMonitor monitor) throws IOException, CancelledException {
|
private void writeStructureBlock(Structure struct, StringBuilder code, Set<String> dependencies) {
|
||||||
// Write forward declaration first
|
String structName = struct.getDisplayName();
|
||||||
this.writer.write("typedef union " + union.getDisplayName() + " " + union.getDisplayName() + ", *P" + union.getDisplayName() + ";");
|
|
||||||
this.writer.write(EOL);
|
|
||||||
this.writer.write(EOL);
|
|
||||||
|
|
||||||
// Then write the body
|
// Struct definition
|
||||||
this.writeCompositeBody(union, monitor);
|
code.append("struct ").append(structName).append(" {");
|
||||||
}
|
String descrip = struct.getDescription();
|
||||||
|
|
||||||
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();
|
|
||||||
if (descrip != null && descrip.length() > 0) {
|
if (descrip != null && descrip.length() > 0) {
|
||||||
String var10001 = this.comment(descrip);
|
code.append(" ").append(comment(descrip));
|
||||||
sb.append(" " + var10001);
|
|
||||||
}
|
}
|
||||||
|
code.append(EOL);
|
||||||
sb.append(EOL);
|
|
||||||
DataTypeComponent[] var6 = composite.getComponents();
|
// Process components
|
||||||
int var7 = var6.length;
|
for (DataTypeComponent component : struct.getComponents()) {
|
||||||
|
writeComponentBlock(component, struct, code, dependencies);
|
||||||
for (int var8 = 0; var8 < var7; ++var8) {
|
|
||||||
DataTypeComponent component = var6[var8];
|
|
||||||
monitor.checkCancelled();
|
|
||||||
this.writeComponent(component, composite, sb, monitor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.append(this.annotator.getSuffix(composite, (DataTypeComponent) null));
|
code.append(annotator.getSuffix(struct, null));
|
||||||
sb.append("};");
|
code.append("};");
|
||||||
this.writer.write(sb.toString());
|
|
||||||
this.writer.write(EOL);
|
|
||||||
this.writer.write(EOL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeComponent(DataTypeComponent component, Composite composite, StringBuilder sb, TaskMonitor monitor)
|
private void writeUnionBlock(Union union, StringBuilder code, Set<String> dependencies) {
|
||||||
throws IOException, CancelledException {
|
String unionName = union.getDisplayName();
|
||||||
sb.append(" ");
|
|
||||||
sb.append(this.annotator.getPrefix(composite, component));
|
// 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();
|
String fieldName = component.getFieldName();
|
||||||
if (fieldName == null || fieldName.length() == 0) {
|
if (fieldName == null || fieldName.length() == 0) {
|
||||||
fieldName = component.getDefaultFieldName();
|
fieldName = component.getDefaultFieldName();
|
||||||
}
|
}
|
||||||
|
|
||||||
DataType componentDataType = component.getDataType();
|
DataType componentDataType = component.getDataType();
|
||||||
sb.append(this.getTypeDeclaration(fieldName, componentDataType, component.getLength(), false, monitor));
|
|
||||||
sb.append(";");
|
// Add dependency only if it's not a pointer (pointers can be forward declared)
|
||||||
sb.append(this.annotator.getSuffix(composite, component));
|
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();
|
String comment = component.getComment();
|
||||||
if (comment != null && comment.length() > 0) {
|
if (comment != null && comment.length() > 0) {
|
||||||
String var10001 = this.comment(comment);
|
code.append(" ").append(comment(comment));
|
||||||
sb.append(" " + var10001);
|
|
||||||
}
|
}
|
||||||
|
code.append(EOL);
|
||||||
sb.append(EOL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTypeDeclaration(String name, DataType dataType, int instanceLength, boolean writeEnabled,
|
private void writeEnumBlock(Enum enumm, StringBuilder code, Set<String> dependencies) {
|
||||||
TaskMonitor monitor) throws IOException, CancelledException {
|
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) {
|
if (name == null) {
|
||||||
name = "";
|
name = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
String componentString = null;
|
|
||||||
if (dataType instanceof Dynamic) {
|
if (dataType instanceof BitFieldDataType) {
|
||||||
// Simplified dynamic handling - just use the display name
|
BitFieldDataType bfDt = (BitFieldDataType) dataType;
|
||||||
componentString = dataType.getDisplayName();
|
name = name + ":" + bfDt.getDeclaredBitSize();
|
||||||
if (name.length() != 0) {
|
dataType = bfDt.getBaseDataType();
|
||||||
componentString = componentString + " " + name;
|
|
||||||
}
|
|
||||||
sb.append(componentString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (componentString == null) {
|
// Handle arrays and pointers
|
||||||
if (dataType instanceof BitFieldDataType) {
|
while (dataType instanceof Array) {
|
||||||
BitFieldDataType bfDt = (BitFieldDataType) dataType;
|
Array array = (Array) dataType;
|
||||||
name = name + ":" + bfDt.getDeclaredBitSize();
|
name = name + "[" + array.getNumElements() + "]";
|
||||||
dataType = bfDt.getBaseDataType();
|
dataType = array.getDataType();
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
private String getDataTypePrefix(DataType dataType) {
|
||||||
dataType = this.getBaseDataType(dataType);
|
dataType = getBaseDataType(dataType);
|
||||||
if (dataType instanceof Structure) {
|
if (dataType instanceof Structure) {
|
||||||
return "struct ";
|
return "struct ";
|
||||||
} else if (dataType instanceof Union) {
|
} else if (dataType instanceof Union) {
|
||||||
return "union ";
|
return "union ";
|
||||||
|
} else if (dataType instanceof Enum) {
|
||||||
|
return "enum ";
|
||||||
} else {
|
} else {
|
||||||
return dataType instanceof Enum ? "enum " : "";
|
return "";
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isIntegral(String typedefName, String basetypeName) {
|
private boolean isIntegral(String typedefName, String basetypeName) {
|
||||||
String[] var3 = INTEGRAL_TYPES;
|
for (String type : INTEGRAL_TYPES) {
|
||||||
int var4 = var3.length;
|
|
||||||
|
|
||||||
int var5;
|
|
||||||
for (var5 = 0; var5 < var4; ++var5) {
|
|
||||||
String type = var3[var5];
|
|
||||||
if (typedefName.equals(type)) {
|
if (typedefName.equals(type)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean endsWithIntegralType = false;
|
boolean endsWithIntegralType = false;
|
||||||
String[] var10 = INTEGRAL_TYPES;
|
for (String type : INTEGRAL_TYPES) {
|
||||||
var5 = var10.length;
|
|
||||||
|
|
||||||
int var13;
|
|
||||||
for (var13 = 0; var13 < var5; ++var13) {
|
|
||||||
String type = var10[var13];
|
|
||||||
if (typedefName.endsWith(" " + type)) {
|
if (typedefName.endsWith(" " + type)) {
|
||||||
endsWithIntegralType = true;
|
endsWithIntegralType = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean containsIntegralModifier = false;
|
for (String modifier : INTEGRAL_MODIFIERS) {
|
||||||
String[] var12 = INTEGRAL_MODIFIERS;
|
|
||||||
var13 = var12.length;
|
|
||||||
|
|
||||||
for (int var14 = 0; var14 < var13; ++var14) {
|
|
||||||
String modifier = var12[var14];
|
|
||||||
if (typedefName.indexOf(modifier + " ") >= 0 || typedefName.indexOf(" " + modifier) >= 0) {
|
if (typedefName.indexOf(modifier + " ") >= 0 || typedefName.indexOf(" " + modifier) >= 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endsWithIntegralType && containsIntegralModifier) {
|
if (endsWithIntegralType) {
|
||||||
return true;
|
return true;
|
||||||
} else if (typedefName.endsWith(" " + basetypeName)) {
|
} else if (typedefName.endsWith(" " + basetypeName)) {
|
||||||
return containsIntegralModifier;
|
return false; // Let it through as a regular typedef
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeDynamicBuiltIn(Dynamic dt, TaskMonitor monitor) throws IOException, CancelledException {
|
private List<Block> topologicalSort(Map<String, Block> blocks) {
|
||||||
// Simplified - don't auto-discover replacement types
|
List<Block> result = new ArrayList<>();
|
||||||
// Just write a comment about the dynamic type
|
Set<String> visited = new HashSet<>();
|
||||||
this.writer.write(this.comment("Dynamic type: " + dt.getDisplayName()));
|
Set<String> visiting = new HashSet<>();
|
||||||
this.writer.write(EOL);
|
|
||||||
this.writer.write(EOL);
|
for (Block block : blocks.values()) {
|
||||||
}
|
if (!visited.contains(block.dataType.getDisplayName())) {
|
||||||
|
topologicalSortVisit(block, blocks, visited, visiting, result);
|
||||||
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(", ");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (hasVarArgs) {
|
private void topologicalSortVisit(Block block, Map<String, Block> blocks,
|
||||||
buf.append("...");
|
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) {
|
if (visited.contains(blockName)) {
|
||||||
buf.append(VoidDataType.dataType.getName());
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.append(")");
|
visiting.add(blockName);
|
||||||
return buf.toString();
|
|
||||||
|
// 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