public static CSharpElement ConvertEnumItem(CSharpConverter converter, CppEnumItem cppEnumItem, CSharpElement context) { // If the context is not an enum, we don't support this scenario. if (!(context is CSharpEnum csEnum)) { return(null); } var enumItemName = converter.GetCSharpName(cppEnumItem, context); var csEnumItem = new CSharpEnumItem(enumItemName) { CppElement = cppEnumItem }; csEnum.Members.Add(csEnumItem); csEnumItem.Comment = converter.GetCSharpComment(cppEnumItem, context); // Process any enum item value expression (e.g ENUM_ITEM = 1 << 2) if (cppEnumItem.ValueExpression != null) { var integerValue = converter.ConvertExpression(cppEnumItem.ValueExpression); csEnumItem.Value = $"unchecked(({csEnum.IntegerBaseType}){(string.IsNullOrEmpty(integerValue) ? cppEnumItem.Value + "" : integerValue)})"; // Tag the enum has flags if (!csEnum.IsFlags && csEnumItem.Value.Contains("<<")) { csEnum.IsFlags = true; } if (csEnum.IsFlags) { csEnumItem.Value = csEnumItem.Value.Replace("<<", $" << ({csEnum.IntegerBaseType})"); } } if (converter.Options.GenerateEnumItemAsFields && context.Parent is CSharpClass csClass) { var csEnumItemAsField = new CSharpField(enumItemName) { Modifiers = CSharpModifiers.Const, FieldType = csEnum, Comment = csEnumItem.Comment, InitValue = $"{csEnum.Name}.{csEnumItem.Name}" }; converter.ApplyDefaultVisibility(csEnumItemAsField, csClass); csClass.Members.Add(csEnumItemAsField); } return(csEnumItem); }
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(); }; }
private static void GenerateDwarfAttributes(CSharpNamespace ns) { var alreadyDone = new HashSet <string>(); var csHelper = new CSharpClass("DwarfHelper") { Modifiers = CSharpModifiers.Static | CSharpModifiers.Partial, Visibility = CSharpVisibility.Public }; ns.Members.Add(csHelper); var csField = new CSharpField("AttributeToEncoding") { Modifiers = CSharpModifiers.Static | CSharpModifiers.ReadOnly, Visibility = CSharpVisibility.Private, FieldType = new CSharpArrayType(new CSharpFreeType("DwarfAttributeEncoding")) }; csHelper.Members.Add(csField); var fieldArrayBuilder = new StringBuilder(); fieldArrayBuilder.AppendLine("new DwarfAttributeEncoding[] {"); int currentAttributeIndex = 0; foreach (var attrEncoding in MapAttributeToEncoding) { var attrEncodingParts = attrEncoding.Split(' ', StringSplitOptions.RemoveEmptyEntries); var attributeName = attrEncodingParts[0]; var attributeIndex = int.Parse(attrEncodingParts[1].Substring(2), System.Globalization.NumberStyles.HexNumber); var rawName = attributeName.Substring("DW_AT_".Length); //var csharpName = CSharpifyName(rawName); string attrType = "object"; var kind = AttributeKind.Managed; if (attributeName == "DW_AT_accessibility") { attrType = "DwarfAccessibility"; kind = AttributeKind.ValueType; } else if (attributeName == "DW_AT_visibility") { attrType = "DwarfVisibility"; kind = AttributeKind.ValueType; } else if (attributeName == "DW_AT_virtuality") { attrType = "DwarfVirtuality"; kind = AttributeKind.ValueType; } else if (attributeName == "DW_AT_language") { attrType = "DwarfLanguageKind"; kind = AttributeKind.ValueType; } else if (attributeName == "DW_AT_identifier_case") { attrType = "DwarfIdentifierCaseKind"; kind = AttributeKind.ValueType; } else if (attributeName == "DW_AT_calling_convention") { attrType = "DwarfCallingConvention"; kind = AttributeKind.ValueType; } else if (attributeName == "DW_AT_inline") { attrType = "DwarfInlineKind"; kind = AttributeKind.ValueType; } else if (attributeName == "DW_AT_ordering") { attrType = "DwarfArrayOrderingKind"; kind = AttributeKind.ValueType; } else if (attributeName == "DW_AT_discr_list") { attrType = "DwarfDiscriminantListKind"; kind = AttributeKind.ValueType; } else if (attrEncodingParts.Length == 3) { switch (attrEncodingParts[2]) { case "string": attrType = "string"; break; case "flag": attrType = "bool"; kind = AttributeKind.ValueType; break; case "reference": attrType = "DwarfDIE"; break; case "address": attrType = "ulong"; kind = AttributeKind.ValueType; break; case "constant": attrType = "DwarfConstant"; kind = AttributeKind.ValueType; break; case "lineptr": attrType = "DwarfLineProgramTable"; break; case "exprloc": attrType = "DwarfExpression"; break; case "loclist": case "loclistptr": attrType = "DwarfLocation"; break; case "addrptr": case "macptr": case "rnglist": case "rangelistptr": case "rnglistsptr": case "stroffsetsptr": attrType = "ulong"; kind = AttributeKind.ValueType; break; } } else if (attrEncodingParts.Length > 3) { var key = string.Join(" ", attrEncodingParts.Skip(2).ToArray()); alreadyDone.Add(key); Console.WriteLine(attrEncoding); bool hasConstant = false; for (int i = 2; i < attrEncodingParts.Length; i++) { switch (attrEncodingParts[i]) { case "loclist": case "loclistptr": attrType = "DwarfLocation"; kind = AttributeKind.ValueType; goto next; case "constant": hasConstant = true; break; } } if (hasConstant) { attrType = "DwarfConstant"; kind = AttributeKind.ValueType; } } next: MapAttributeCompactNameToType.Add(attributeName.Replace("_", string.Empty), new AttributeMapping(rawName, attrType, kind)); const int PaddingEncodingName = 50; for (; currentAttributeIndex < attributeIndex; currentAttributeIndex++) { fieldArrayBuilder.AppendLine($" {"DwarfAttributeEncoding.None",-PaddingEncodingName}, // 0x{currentAttributeIndex:x2} (undefined)"); } for (int i = 2; i < attrEncodingParts.Length; i++) { string name; switch (attrEncodingParts[i]) { case "string": name = "String"; break; case "flag": name = "Flag"; break; case "block": name = "Block"; break; case "reference": name = "Reference"; break; case "address": name = "Address"; break; case "constant": name = "Constant"; break; case "lineptr": name = "LinePointer"; break; case "exprloc": name = "ExpressionLocation"; break; case "loclist": name = "LocationList"; break; case "loclistptr": name = "LocationListPointer"; break; case "loclistsptr": name = "LocationListsPointer"; break; case "addrptr": name = "AddressPointer"; break; case "macptr": name = "MacroPointer"; break; case "rnglist": name = "RangeList"; break; case "rangelistptr": name = "RangeListPointer"; break; case "rnglistsptr": name = "RangeListsPointer"; break; case "stroffsetsptr": name = "StringOffsetPointer"; break; default: throw new InvalidOperationException($"Unknown encoding {attrEncodingParts[i]}"); } bool isLast = i + 1 == attrEncodingParts.Length; fieldArrayBuilder.Append($" {"DwarfAttributeEncoding." + name + (isLast ? "" : " | "),-PaddingEncodingName}"); if (isLast) { fieldArrayBuilder.Append($", // 0x{currentAttributeIndex:x2} {attributeName} "); } fieldArrayBuilder.AppendLine(); } currentAttributeIndex++; } fieldArrayBuilder.Append(" }"); csField.InitValue = fieldArrayBuilder.ToString(); Console.WriteLine(); foreach (var key in alreadyDone.ToArray().OrderBy(x => x)) { Console.WriteLine(key); } }
/// <summary> /// Initializes a new instance of the <see cref="FieldGenerator"/> class for the specified <see cref="IndentedStreamWriter"/> /// </summary> /// <param name="field">Field to generate</param> /// <param name="writer"><see cref="IndentedStreamWriter"/> used to write to</param> public FieldGenerator(CSharpField field, IndentedStreamWriter writer) : base(writer) => _field = field;