Ejemplo n.º 1
0
        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();
            };
        }