diff --git a/Source/generator/ClassBase.cs b/Source/generator/ClassBase.cs index f2dee2630..fb6a6e86a 100644 --- a/Source/generator/ClassBase.cs +++ b/Source/generator/ClassBase.cs @@ -90,6 +90,9 @@ namespace GtkSharp.Generation { abi_field = new StructABIField (member, this); abi_fields.Add (abi_field); } + } else if (node.Name == "union") { + abi_field = new UnionABIField (member, this); + abi_fields.Add (abi_field); } if (member.GetAttributeAsBoolean ("hidden")) diff --git a/Source/generator/DESIGN b/Source/generator/DESIGN index 616b6d778..287124408 100644 --- a/Source/generator/DESIGN +++ b/Source/generator/DESIGN @@ -109,6 +109,7 @@ PropertyBase: Abstract base class for property-like elements ObjectField: Handles elements in objects StructField: Handles elements in structs StructABIField: Handles to generate ABI compatible structures + UnionABIField: Handles to generate ABI compatible structures ClassField: Handles elements in classes Property: Handles elements ChildProperty: Handles elements diff --git a/Source/generator/UnionABIField.cs b/Source/generator/UnionABIField.cs new file mode 100644 index 000000000..d51ce1212 --- /dev/null +++ b/Source/generator/UnionABIField.cs @@ -0,0 +1,96 @@ +namespace GtkSharp.Generation { + + using System; + using System.Collections; + using System.IO; + using System.Xml; + using System.Collections.Generic; + + public class UnionSubstruct { + List fields; + XmlElement Elem; + bool is_valid; + bool unique_field; + + public UnionSubstruct(XmlElement elem, ClassBase container_type) { + fields = new List (); + Elem = elem; + is_valid = true; + unique_field = false; + + if (Elem.Name == "struct") { + foreach (XmlElement child_field in elem.ChildNodes) { + if (child_field.Name != "field") { + is_valid = false; + continue; + } + + fields.Add(new StructABIField (child_field, container_type)); + } + } else if (Elem.Name == "field") { + fields.Add(new StructABIField (Elem, container_type)); + unique_field = true; + } + } + + public void Generate(GenerationInfo gen_info, string indent){ + StreamWriter sw = gen_info.Writer; + var name = Elem.GetAttribute("name"); + var cname = Elem.GetAttribute("cname"); + + if (unique_field) { + sw.WriteLine (indent + "[FieldOffset(0)]"); + foreach (StructABIField field in fields) + field.Generate(gen_info, indent); + + return; + } + + sw.WriteLine (indent + "struct __" + name + "{"); + foreach (StructABIField field in fields) { + field.Generate(gen_info, indent + "\t"); + } + sw.WriteLine (indent + "}"); + sw.WriteLine (indent + "[FieldOffset(0)]"); + sw.WriteLine (indent + "private __" + name + " " + cname + ";"); + } + } + + public class UnionABIField : StructABIField { + bool is_valid; + XmlElement Elem; + protected List substructs = new List (); + + + public UnionABIField (XmlElement elem, ClassBase container_type) : base (elem, container_type) { + Elem = elem; + is_valid = true; + foreach (XmlElement union_child in elem.ChildNodes) { + substructs.Add(new UnionSubstruct(union_child, container_type)); + } + } + + public override void Generate (GenerationInfo gen_info, string indent) { + StreamWriter sw = gen_info.Writer; + var name = Elem.GetAttribute("name"); + var cname = Elem.GetAttribute("cname"); + + sw.WriteLine (indent + "[StructLayout(LayoutKind.Explicit)]"); + sw.WriteLine (indent + "struct __" + name + " {"); + foreach (UnionSubstruct _struct in substructs) { + _struct.Generate(gen_info, indent + "\t"); + } + sw.WriteLine (indent + "}"); + sw.WriteLine (indent + "private __" + name + " " + cname + ";"); + } + + public override bool Validate (LogWriter log) + { + + if (!is_valid) { + log.Warn("Can't generate ABI compatible union"); + } + return is_valid; + } + } +} diff --git a/Source/generator/meson.build b/Source/generator/meson.build index f42add2d6..9212afbb2 100644 --- a/Source/generator/meson.build +++ b/Source/generator/meson.build @@ -62,6 +62,7 @@ gapi_codegen = executable('gapi_codegen', 'StructField.cs', 'StructGen.cs', 'SymbolTable.cs', + 'UnionABIField.cs', 'UnionGen.cs', 'VirtualMethod.cs', 'VMSignature.cs',