private static void ProcessElfEnum(CSharpConverterOptions cppOptions, CSharpCompilation csCompilation, string enumPrefix, string enumClassName) { var ns = csCompilation.Members.OfType <CSharpGeneratedFile>().First().Members.OfType <CSharpNamespace>().First(); var rawElfClass = ns.Members.OfType <CSharpClass>().First(); var enumRawFields = rawElfClass.Members.OfType <CSharpField>().Where(x => (x.Modifiers & CSharpModifiers.Const) != 0 && x.Name.StartsWith(enumPrefix)).ToList(); var enumClass = new CSharpStruct(enumClassName) { Modifiers = CSharpModifiers.Partial | CSharpModifiers.ReadOnly }; ns.Members.Add(enumClass); bool isReloc = enumPrefix == "R_"; var filteredFields = new List <CSharpField>(); foreach (var enumRawField in enumRawFields) { var rawName = enumRawField.Name; string relocArch = null; if (isReloc) { foreach (var mapReloc in MapRelocMachineToArch) { if (rawName.StartsWith(mapReloc.Key)) { relocArch = mapReloc.Value; break; } } if (relocArch == null) { continue; } } // NUM fields if (rawName.EndsWith("_NUM")) { continue; } filteredFields.Add(enumRawField); var csFieldName = isReloc ? rawName : rawName.Substring(enumPrefix.Length); // discard EM_ if (csFieldName.StartsWith("386")) { csFieldName = $"I{csFieldName}"; } else { switch (csFieldName) { case "88K": csFieldName = "M88K"; break; case "860": csFieldName = "I860"; break; case "960": csFieldName = "I960"; break; default: // assume Motorola if (csFieldName.StartsWith("68")) { csFieldName = $"M{csFieldName}"; } break; } } if (char.IsDigit(csFieldName[0])) { throw new InvalidOperationException($"The enum name `{rawName}` starts with a number and needs to be modified"); } csFieldName = CSharpHelper.EscapeName(csFieldName); var enumField = new CSharpField(csFieldName) { Modifiers = CSharpModifiers.Static | CSharpModifiers.ReadOnly, FieldType = enumClass, Visibility = CSharpVisibility.Public, Comment = enumRawField.Comment, InitValue = relocArch != null ? $"new {enumClass.Name}(ElfArch.{relocArch}, {cppOptions.DefaultClassLib}.{rawName})" : $"new {enumClass.Name}({cppOptions.DefaultClassLib}.{rawName})" }; enumClass.Members.Add(enumField); } var toStringInternal = new CSharpMethod() { Name = "ToStringInternal", Visibility = CSharpVisibility.Private, ReturnType = CSharpPrimitiveType.String }; enumClass.Members.Add(toStringInternal); toStringInternal.Body = (writer, element) => { var values = new HashSet <object>(); if (isReloc) { writer.WriteLine("switch (((ulong)Value << 16) | Arch.Value)"); } else { writer.WriteLine("switch (Value)"); } writer.OpenBraceBlock(); foreach (var rawField in filteredFields) { var cppField = ((CppField)rawField.CppElement); if (isReloc) { string relocMachine = null; foreach (var mapReloc in MapRelocMachineToMachine) { if (rawField.Name.StartsWith(mapReloc.Key)) { relocMachine = mapReloc.Value; break; } } if (relocMachine == null) { continue; } if (!values.Add(relocMachine + "$" + cppField.InitValue.Value)) { continue; } writer.WriteLine($"case ((ulong){cppOptions.DefaultClassLib}.{rawField.Name} << 16) | {cppOptions.DefaultClassLib}.{relocMachine} : return \"{rawField.Name}\";"); } else { if (!values.Add(cppField.InitValue.Value)) { continue; } string descriptionText = rawField.Name; if (cppField.Comment != null) { descriptionText += " - " + cppField.Comment.ToString().Replace("\"", "\\\""); } descriptionText = descriptionText.Replace("\r\n", "").Replace("\n", ""); writer.WriteLine($"case {cppOptions.DefaultClassLib}.{rawField.Name}: return \"{descriptionText}\";"); } } writer.WriteLine($"default: return \"Unknown {enumClassName}\";"); writer.CloseBraceBlock(); }; }