diff --git a/DwarfOne2C/CWriter/CWriter.cs b/DwarfOne2C/CWriter/CWriter.cs index 580c189..7e352ac 100644 --- a/DwarfOne2C/CWriter/CWriter.cs +++ b/DwarfOne2C/CWriter/CWriter.cs @@ -20,7 +20,8 @@ public CWriter(string outputDirectory, string splitPath) } public void GenerateCode( - RootTag unit, + CompilationUnit unit, + List allUnits, List allTags, Dictionary IDToIndex) { @@ -28,39 +29,50 @@ public void GenerateCode( || splitPath.EndsWith('/')) splitPath = splitPath.Remove(splitPath.Length - 1); - outputPath = unit.name.Replace(splitPath, string.Empty); + outputPath = unit.root.tag.name.Replace(splitPath, string.Empty); if(Path.DirectorySeparatorChar == '/') outputPath = outputPath.Replace('\\', '/'); outputPath = Path.Join(outputDirectory, outputPath); - Tag current = allTags[IDToIndex[unit.firstChild]]; + List allCUs = allUnits.Select(CU => CU.root).ToList(); - // TODO - List memberFuncs = new(), staticMembers = new(); - /*List memberFuncs = unit.childTags - .Where(i => i.tagType == TagType.GlobalFunc && i.memberOfID >= 0) + List memberFuncs = unit.root.children + .Where( + i => + { + return i.tag.tagType == TagType.GlobalFunc + && i.tag.memberOfID >= 0; + }) .ToList(); - Func predicate = i => + Func predicate = i => { - return unit.childTags.Where(j => j.tagType == TagType.TypeDef) - .Any(j => j.name == i.name); + return unit.root.children + .Where(j => j.tag.tagType == TagType.TypeDef) + .Any(j => j.tag.name == i.tag.name); }; // Filled by classes and structs - List staticMembers = unit.childTags - .Where(i => i.tagType == TagType.GlobalVar) + List staticMembers = unit.root.children + .Where(i => i.tag.tagType == TagType.GlobalVar) .Where(predicate) - .ToList();*/ + .ToList(); - for(; - current.sibling != Tag.NoSibling; - current = allTags[IDToIndex[current.sibling]]) + foreach(Node child in unit.root.children) { + Tag current = child.tag; + code.AddRange( - TagDispatcher(allTags, memberFuncs, IDToIndex, current, 0)); + TagDispatcher( + allTags, + memberFuncs, + IDToIndex, + unit.root, + allCUs, + child, + 0)); switch(current.tagType) { @@ -70,18 +82,30 @@ public void GenerateCode( continue; code.AddRange( - GenerateFunction(allTags, IDToIndex, current, 0)); + GenerateFunction( + allTags, + IDToIndex, + unit.root, + allCUs, + child, + 0)); } break; case TagType.CULocalFunc: { code.Add("// Local to compilation unit"); code.AddRange( - GenerateFunction(allTags, IDToIndex, current, 0)); + GenerateFunction( + allTags, + IDToIndex, + unit.root, + allCUs, + child, + 0)); } break; case TagType.GlobalVar: { - if(staticMembers.Contains(current)) + if(staticMembers.Contains(child)) continue; if(current.comment != null) @@ -93,7 +117,9 @@ public void GenerateCode( (string part1, string part2) = GetType( allTags, IDToIndex, - current); + unit.root, + allCUs, + child); string line = string.Format( "{0}{1}{2};", @@ -117,7 +143,9 @@ public void GenerateCode( (string part1, string part2) = GetType( allTags, IDToIndex, - current); + unit.root, + allCUs, + child); string line = string.Format( "static {0}{1}{2};", @@ -155,48 +183,61 @@ public void WriteCode() private static List TagDispatcher( List allTags, - List memberFuncs, + List memberFuncs, Dictionary IDToIndex, - Tag current, + Node CU, + List allCUs, + Node current, int depth) { List code = new(); - switch(current.tagType) + switch(current.tag.tagType) { case TagType.Class: - // Parse class + { code.AddRange( GenerateClassStruct( true, allTags, memberFuncs, IDToIndex, + CU, + allCUs, current, depth)); - break; + } break; case TagType.Struct: - // Parse struct + { code.AddRange( GenerateClassStruct( false, allTags, memberFuncs, IDToIndex, + CU, + allCUs, current, depth)); - break; + } break; case TagType.Union: - // Parse union - code.AddRange(GenerateUnion(allTags, IDToIndex, current, depth)); - break; + { + code.AddRange( + GenerateUnion(allTags, IDToIndex, CU, allCUs, current, depth)); + } break; case TagType.Enum: - code.AddRange(GenerateEnum(allTags, IDToIndex, current, depth)); + code.AddRange(GenerateEnum(allTags, IDToIndex, current.tag, depth)); break; case TagType.MemberFunc: { code.AddRange( - GenerateMemberFunction(allTags, IDToIndex, current, depth)); + GenerateMemberFunction( + allTags, + IDToIndex, + CU, + allCUs, + current, + depth)); } break; } diff --git a/DwarfOne2C/CWriter/Class.cs b/DwarfOne2C/CWriter/Class.cs index fa20781..0402897 100644 --- a/DwarfOne2C/CWriter/Class.cs +++ b/DwarfOne2C/CWriter/Class.cs @@ -8,11 +8,15 @@ public partial class CWriter private static List GenerateClassStruct( bool isClass, List allTags, - List allMemberFuncs, + List allMemberFuncs, Dictionary IDToIndex, - Tag current, + Node CU, + List allCUs, + Node classNode, int depth) { + Tag current = classNode.tag; + List code = new(); string tabs = new('\t', depth); @@ -26,7 +30,7 @@ private static List GenerateClassStruct( isClass ? "class" : "struct", current.name); - if(current.firstChild == -1) + if(classNode.children.Count == 0) { if(current.name == null) code.Add(tabs + "// size: " + current.size + " bytes"); @@ -39,7 +43,7 @@ private static List GenerateClassStruct( return code; } - Tag child = allTags[IDToIndex[current.firstChild]]; + Tag child = classNode.children[0].tag; bool firstInherit = true; while(child.tagType == TagType.Inheritance) @@ -60,69 +64,67 @@ private static List GenerateClassStruct( code.Add(line); code.Add(tabs + "{"); - List children = new(); - - for(/* child */; - child.sibling != Tag.NoSibling; - child = allTags[IDToIndex[child.sibling]]) - { - // This is perhaps not needed anymore... - // Work around weirdness where anonymous structs are generated - // with members (padding) and functions (padding) as children. - /*if(child.tagType == TagType.Member - || child.tagType == TagType.TypeDef)*/ - children.Add(child); - } - // Assume children are in the correct order // Could contain unions - List childrenWithLocation = children - .Where(i => i.location >= 0) + List childrenWithLocation = classNode.children + .Where(i => i.tag.location >= 0) .ToList(); - for(int i = 0; i < childrenWithLocation.Count; ++i) + int i = 0; + + for(; i < childrenWithLocation.Count; ++i) { - child = childrenWithLocation[i]; + child = childrenWithLocation[i].tag; // Detect anonymous unions - Tag first = childrenWithLocation - .First(i => i.location == child.location); + Node first = childrenWithLocation + .First(i => i.tag.location == child.location); - Tag last = childrenWithLocation - .Last(i => i.location == child.location); + Node last = childrenWithLocation + .Last(i => i.tag.location == child.location); if(first != last) { int firstIndex = childrenWithLocation.IndexOf(first); int lastIndex = childrenWithLocation.IndexOf(last); - List slice = childrenWithLocation.GetRange( + List slice = childrenWithLocation.GetRange( firstIndex, lastIndex - firstIndex + 1); // If all are on the same location AND all are bitfields // assume it's not a union. - if(!slice.All(i => i.location == first.location && i.bitSize > 0)) - slice.ForEach(i => i.isAnonUnionMember = true); + bool all = slice.All( + i => + { + return i.tag.location == first.tag.location + && i.tag.bitSize > 0; + }); + + if(!all) + slice.ForEach(i => i.tag.isAnonUnionMember = true); } } - while(children.Count > 0 && children[0].tagType == TagType.Inheritance) - children.RemoveAt(0); + while(classNode.children.Count > 0 + && classNode.children[0].tag.tagType == TagType.Inheritance) + ++i; AccessLevel accessLevel = isClass ? AccessLevel.Private : AccessLevel.Public; - for(int i = 0; i < children.Count; ++i) + for(i = 0; i < classNode.children.Count; ++i) { - child = children[i]; + child = classNode.children[i].tag; List innerCode = TagDispatcher( allTags, allMemberFuncs, IDToIndex, - child, + CU, + allCUs, + classNode.children[i], depth + 1); if(innerCode.Count > 0) @@ -147,7 +149,9 @@ private static List GenerateClassStruct( List unionCode = GenerateAnonUnion( allTags, IDToIndex, - children, + CU, + allCUs, + classNode.children, ref i, depth + 1); @@ -155,7 +159,12 @@ private static List GenerateClassStruct( } else { - (string part1, string part2) = GetType(allTags, IDToIndex, child); + (string part1, string part2) = GetType( + allTags, + IDToIndex, + CU, + allCUs, + classNode.children[i]); line = string.Format( "{0}\t{1}{2}{3}{4}{5};{6}", @@ -171,8 +180,8 @@ private static List GenerateClassStruct( } } - IEnumerable memberFuncs = allMemberFuncs - .Where(i => i.memberOfID == current.ID); + IEnumerable memberFuncs = allMemberFuncs + .Where(i => i.tag.memberOfID == current.ID); // Assume all member functions are public, as we don't have the information // to know their access level. @@ -183,10 +192,16 @@ private static List GenerateClassStruct( string extraTabs = new('\t', depth + 1); - foreach(Tag memberFunc in memberFuncs) + foreach(Node memberFunc in memberFuncs) { code.AddRange( - GenerateFunction(allTags, IDToIndex, memberFunc, depth + 1)); + GenerateFunction( + allTags, + IDToIndex, + CU, + allCUs, + memberFunc, + depth + 1)); code.Add(""); } @@ -206,7 +221,9 @@ private static List GenerateClassStruct( private static List GenerateAnonUnion( List allTags, Dictionary IDToIndex, - List members, + Node CU, + List allCUs, + List members, ref int index, int depth) { @@ -221,11 +238,11 @@ private static List GenerateAnonUnion( code.Add(tabs + "union"); code.Add(tabs + "{"); - for(; members[index].isAnonUnionMember; ++index) + for(; members[index].tag.isAnonUnionMember; ++index) { string extraTabs = tabs + new string('\t', extraDepth); - Tag member = members[index]; + Tag member = members[index].tag; if(member.bitSize > 0 && !isStruct) { ++extraDepth; @@ -243,7 +260,7 @@ private static List GenerateAnonUnion( { if(index + 1 < members.Count) { - Tag next = members[index + 1]; + Tag next = members[index + 1].tag; if(next.location < member.location && next.isAnonUnionMember) goto writeMember; @@ -261,7 +278,12 @@ private static List GenerateAnonUnion( extraTabs = tabs + new string('\t', extraDepth); - (string part1, string part2) = GetType(allTags, IDToIndex, member); + (string part1, string part2) = GetType( + allTags, + IDToIndex, + CU, + allCUs, + members[index]); // Static not allowed in anonymous unions (YAY) if(member.bitSize > 0) diff --git a/DwarfOne2C/CWriter/Function.cs b/DwarfOne2C/CWriter/Function.cs index a6ca28f..ee2ed91 100644 --- a/DwarfOne2C/CWriter/Function.cs +++ b/DwarfOne2C/CWriter/Function.cs @@ -7,9 +7,13 @@ public partial class CWriter private static List GenerateFunction( List allTags, Dictionary IDToIndex, - Tag current, + Node CU, + List allCUs, + Node functionNode, int depth) { + Tag current = functionNode.tag; + List code = new(); string tabs = new('\t', depth); @@ -17,7 +21,12 @@ private static List GenerateFunction( if(current.comment != null) code.Add(tabs + "// " + current.comment); - (string part1, string part2) = GetType(allTags, IDToIndex, current); + (string part1, string part2) = GetType( + allTags, + IDToIndex, + CU, + allCUs, + functionNode); // E.g. (With function pointer) // static void (*Foo(int))(int, float); @@ -32,24 +41,29 @@ private static List GenerateFunction( bool firstLocal = true; - if(current.firstChild >= 0) + if(functionNode.children.Count > 0) { bool hasParams = false; int i = 0; - for(Tag child = allTags[IDToIndex[current.firstChild]]; - child.sibling != Tag.NoSibling; - child = allTags[IDToIndex[child.sibling]], ++i) + foreach(Node childNode in functionNode.children) { + Tag child = childNode.tag; + if(child.name == "this") continue; string name = child.name != null ? child.name - : $"unknown{i}"; + : $"unknown{i++}"; - (string pPart1, string pPart2) = GetType(allTags, IDToIndex, child); + (string pPart1, string pPart2) = GetType( + allTags, + IDToIndex, + CU, + allCUs, + childNode); if(child.tagType == TagType.Param) { @@ -142,9 +156,13 @@ private static List GenerateFunction( private static List GenerateMemberFunction( List allTags, Dictionary IDToIndex, - Tag current, + Node CU, + List allCUs, + Node memberFuncNode, int depth) { + Tag current = memberFuncNode.tag; + List code = new(); string tabs = new('\t', depth); @@ -152,16 +170,39 @@ private static List GenerateMemberFunction( if(current.comment != null) code.Add(tabs + "// " + current.comment); - Tag referenced = allTags[IDToIndex[current.typeID]]; + Node referenced = CU.Find(current.typeID); + + if(referenced == null) + { + for(int i = 0; i < allCUs.Count; ++i) + { + Node unit = allCUs[i]; + + if(i < allCUs.Count - 2) + { + Node nextUnit = allCUs[i + 1]; + + if(nextUnit.tag.ID < current.typeID) + continue; + } + + referenced = unit.Find(current.typeID); + + if(referenced != null) + break; + } + } // Reforge the tag to generate properly. - referenced.tagType = TagType.GlobalFunc; - referenced.name = current.name; + referenced.tag.tagType = TagType.GlobalFunc; + referenced.tag.name = current.name; code.AddRange( GenerateFunction( allTags, IDToIndex, + CU, + allCUs, referenced, depth)); diff --git a/DwarfOne2C/CWriter/Types.cs b/DwarfOne2C/CWriter/Types.cs index 62ef8ec..7e14e8b 100644 --- a/DwarfOne2C/CWriter/Types.cs +++ b/DwarfOne2C/CWriter/Types.cs @@ -71,23 +71,25 @@ private static string GetTypeName( private static (string part1, string part2) GetArray( List allTags, Dictionary IDToIndex, - Tag current) + Node CU, + List allCUs, + Node current) { string type, part2 = ""; - if(current.typeID > 0) + if(current.tag.typeID > 0) { - (type, part2) = GetType(allTags, IDToIndex, current); + (type, part2) = GetType(allTags, IDToIndex, CU, allCUs, current); } else { - type = GetTypeName(allTags, IDToIndex, current); - type += GetModifiers(allTags, IDToIndex, current); + type = GetTypeName(allTags, IDToIndex, current.tag); + type += GetModifiers(allTags, IDToIndex, current.tag); } - if (current.isMultidimArray) + if (current.tag.isMultidimArray) { - foreach (int len in current.arrayDimLengths) + foreach (int len in current.tag.arrayDimLengths) { part2 = string.Format( "[{0}]", @@ -101,9 +103,9 @@ private static (string part1, string part2) GetArray( { part2 = string.Format( "[{0}]", - current.length < 0 + current.tag.length < 0 ? "" - : "" + (current.length + 1)) + : "" + (current.tag.length + 1)) + part2; } @@ -113,9 +115,13 @@ private static (string part1, string part2) GetArray( private static (string part1, string part2) GetFunctionPointer( List allTags, Dictionary IDToIndex, - Tag current, + Node CU, + List allCUs, + Node pointerNode, bool isMemberFunc = false) { + Tag current = pointerNode.tag; + (string part1, string part2) = (null, ""); if(current.typeID < 0) @@ -125,7 +131,7 @@ private static (string part1, string part2) GetFunctionPointer( } else { - (part1, part2) = GetType(allTags, IDToIndex, current); + (part1, part2) = GetType(allTags, IDToIndex, CU, allCUs, pointerNode); part1 += "("; } @@ -133,16 +139,16 @@ private static (string part1, string part2) GetFunctionPointer( sb.Append(')'); sb.Append('('); - if(current.firstChild > -1) + if(pointerNode.children.Count > 0) { int i = 0; - for(Tag child = allTags[IDToIndex[current.firstChild]]; - child.sibling != Tag.NoSibling; - child = allTags[IDToIndex[child.sibling]]) + foreach(Node child in pointerNode.children) { (string pPart1, string pPart2) = GetType( allTags, IDToIndex, + CU, + allCUs, child); sb.Append(pPart1); @@ -166,14 +172,44 @@ private static (string part1, string part2) GetFunctionPointer( private static (string part1, string part2) GetMemberFunctionPointer( List allTags, Dictionary IDToIndex, - Tag current) + Node CU, + List allCUs, + Node current) { - Tag referenced = allTags[IDToIndex[current.typeID]]; - (string part1, string part2) = GetType(allTags, IDToIndex, referenced); + Node referenced = CU.Find(current.tag.typeID); + + if(referenced == null) + { + for(int i = 0; i < allCUs.Count; ++i) + { + Node unit = allCUs[i]; + + if(i < allCUs.Count - 2) + { + Node nextUnit = allCUs[i + 1]; + + if(nextUnit.tag.ID < current.tag.typeID) + continue; + } + + referenced = unit.Find(current.tag.typeID); + + if(referenced != null) + break; + } + } + + (string part1, string part2) = GetType( + allTags, + IDToIndex, + CU, + allCUs, + referenced); + + Tag refClass = allTags[IDToIndex[current.tag.memberOfID]]; - Tag refClass = allTags[IDToIndex[current.memberOfID]]; part1 += refClass.name + "::"; - part1 += GetModifiers(allTags, IDToIndex, current, false); + part1 += GetModifiers(allTags, IDToIndex, current.tag, false); return (part1, part2); } @@ -181,34 +217,66 @@ private static (string part1, string part2) GetMemberFunctionPointer( private static (string part1, string part2) GetType( List allTags, Dictionary IDToIndex, - Tag current) + Node CU, + List allCUs, + Node current) { string part1, part2 = ""; - Tag referenced = current; + Node referenced = current; - if(current.typeID > 0) + if(current.tag.typeID > 0) { - referenced = allTags[IDToIndex[current.typeID]]; + referenced = CU.Find(current.tag.typeID); + + if(referenced == null) + { + for(int i = 0; i < allCUs.Count; ++i) + { + Node unit = allCUs[i]; + + if(i < allCUs.Count - 2) + { + Node nextUnit = allCUs[i + 1]; + + if(nextUnit.tag.ID < current.tag.typeID) + continue; + } + + referenced = unit.Find(current.tag.typeID); + + if(referenced != null) + break; + } + } } - if(referenced.tagType == TagType.ArrayType) - (part1, part2) = GetArray(allTags, IDToIndex, referenced); - else if(referenced.tagType == TagType.FunctionPointer) + if(referenced.tag.tagType == TagType.ArrayType) + { + (part1, part2) = GetArray(allTags, IDToIndex, CU, allCUs, referenced); + } + else if(referenced.tag.tagType == TagType.FunctionPointer) { - (part1, part2) = GetFunctionPointer(allTags, IDToIndex, referenced); + (part1, part2) = GetFunctionPointer( + allTags, + IDToIndex, + CU, + allCUs, + referenced); } - else if(referenced.tagType == TagType.PtrToMemberFunc) + else if(referenced.tag.tagType == TagType.PtrToMemberFunc) { (part1, part2) = GetMemberFunctionPointer( allTags, IDToIndex, + CU, + allCUs, referenced); } else - part1 = GetTypeName(allTags, IDToIndex, referenced); + part1 = GetTypeName(allTags, IDToIndex, referenced.tag); - part1 += GetModifiers(allTags, IDToIndex, current, false); + part1 += GetModifiers(allTags, IDToIndex, current.tag, false); return (part1, part2); } diff --git a/DwarfOne2C/CWriter/Union.cs b/DwarfOne2C/CWriter/Union.cs index 0a10ce8..3220237 100644 --- a/DwarfOne2C/CWriter/Union.cs +++ b/DwarfOne2C/CWriter/Union.cs @@ -8,9 +8,13 @@ public partial class CWriter private static List GenerateUnion( List allTags, Dictionary IDToIndex, - Tag current, + Node CU, + List allCUs, + Node unionNode, int depth) { + Tag current = unionNode.tag; + List code = new(); string tabs = new('\t', depth); @@ -21,7 +25,7 @@ private static List GenerateUnion( code.Add(string.Format("{0}union {1}", tabs, current.name)); code.Add(tabs + "{"); - if(current.firstChild == -1) + if(unionNode.children.Count == 0) { code.Add(tabs + "};"); code.Add(""); @@ -29,14 +33,19 @@ private static List GenerateUnion( return code; } - for(Tag child = allTags[IDToIndex[current.firstChild]]; - child.sibling != Tag.NoSibling; - child = allTags[IDToIndex[child.sibling]]) + foreach(Node childNode in unionNode.children) { + Tag child = childNode.tag; + if(child.tagType != TagType.Member) throw new NotImplementedException("?????"); - (string part1, string part2) = GetType(allTags, IDToIndex, child); + (string part1, string part2) = GetType( + allTags, + IDToIndex, + CU, + allCUs, + childNode); code.Add( string.Format( diff --git a/DwarfOne2C/Parsing/DumpParser.cs b/DwarfOne2C/Parsing/DumpParser.cs index f39f364..c8be298 100644 --- a/DwarfOne2C/Parsing/DumpParser.cs +++ b/DwarfOne2C/Parsing/DumpParser.cs @@ -49,7 +49,7 @@ public void ListCompilationUnits() } } - public List Parse() + public List Parse() { List units = new(100); @@ -65,7 +65,7 @@ public List Parse() units.Add(unit); } - return new(); + return units; } private void Parse(string[] lines, int current) diff --git a/DwarfOne2C/Program.cs b/DwarfOne2C/Program.cs index 2b9acb0..d4d1404 100644 --- a/DwarfOne2C/Program.cs +++ b/DwarfOne2C/Program.cs @@ -107,16 +107,17 @@ static void DumpFiles( DumpParser parser = new(dumpFile.FullName); - List units = parser.Parse(); + List units = parser.Parse(); - Dictionary> sharedNames = new(); + Dictionary> sharedNames = new(); - foreach(RootTag unit in units) + foreach(CompilationUnit unit in units) { - sharedNames.TryAdd(unit.name, new()); - List sharers = sharedNames[unit.name]; + Tag root = unit.root.tag; + sharedNames.TryAdd(root.name, new()); + List sharers = sharedNames[root.name]; - sharers.AddRange(units.Where(c => c.name == unit.name)); + sharers.AddRange(units.Where(c => c.root.tag.name == root.name)); } sharedNames @@ -138,6 +139,7 @@ static void DumpFiles( { writer.GenerateCode( cu, + units, parser.allTags, parser.IDToIndex);