Exemple #1
0
        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);
        }
Exemple #2
0
        private static void ProcessEnum(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);

            CSharpEnum stdEnum = null;

            var enumItemType = enumRawFields[0].FieldType;

            bool isReloc = enumPrefix == "R_";

            if (!isReloc)
            {
                enumClass.Name = enumClass.Name + "Ex";
                stdEnum        = new CSharpEnum(enumClassName)
                {
                    Visibility = CSharpVisibility.Public
                };
                ns.Members.Add(stdEnum);
                stdEnum.BaseTypes.Add(enumItemType);
            }

            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;
                    }
                }

                // skip lo/hi user
                if (rawName.StartsWith("DW_") && (rawName.Contains("_lo_") || rawName.Contains("_hi_")))
                {
                    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");
                }

                if (rawName.StartsWith("DW_"))
                {
                    csFieldName = CSharpifyName(csFieldName);
                }

                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);

                if (!isReloc)
                {
                    var stdEnumField = new CSharpEnumItem(csFieldName, $"{cppOptions.DefaultClassLib}.{rawName}");
                    stdEnum.Members.Add(stdEnumField);
                }
            }

            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) | (ulong)Arch.Value)");
                }
                else
                {
                    writer.WriteLine($"switch (({enumItemType})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 null;");
                writer.CloseBraceBlock();
            };
        }