diff --git a/ChangeLog b/ChangeLog index 127e6a2ff..680c4418e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2004-11-18 Mike Kestner + + * generator/InterfaceGen.cs : beginnings of a real + implementation for GInterfaces. Not quite ready yet, + so it's not active in generation. + 2004-11-18 Mike Kestner * generator/Makefile.am : add new file. diff --git a/generator/InterfaceGen.cs b/generator/InterfaceGen.cs index 6481cf6cd..33c6f9fdf 100644 --- a/generator/InterfaceGen.cs +++ b/generator/InterfaceGen.cs @@ -3,6 +3,7 @@ // Author: Mike Kestner // // Copyright (c) 2001-2003 Mike Kestner +// Copyright (c) 2004 Novell, Inc. // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the GNU General Public @@ -22,12 +23,240 @@ namespace GtkSharp.Generation { using System; + using System.Collections; using System.IO; using System.Xml; public class InterfaceGen : ClassBase, IGeneratable { - public InterfaceGen (XmlElement ns, XmlElement elem) : base (ns, elem) {} + ArrayList vms = new ArrayList (); + ArrayList members = new ArrayList (); + + public InterfaceGen (XmlElement ns, XmlElement elem) : base (ns, elem) + { + foreach (XmlNode node in elem.ChildNodes) { + switch (node.Name) { + case "virtual_method": + VirtualMethod vm = new VirtualMethod (node as XmlElement, this); + vms.Add (vm); + members.Add (vm); + break; + case "signal": + members.Add ((node as XmlElement).GetAttribute ("cname").Replace ('-', '_')); + break; + default: + if (!IsNodeNameHandled (node.Name)) + Console.WriteLine ("Unexpected node " + node.Name + " in " + CName); + break; + } + } + } + + string IfaceName { + get { + return Name + "Iface"; + } + } + + void GenerateDelegates (StreamWriter sw) + { + if (vms.Count == 0) + return; + + foreach (VirtualMethod vm in vms) { + sw.WriteLine ("\t\t" + vm.NativeDelegate); + } + sw.WriteLine (); + } + + void GenerateIfaceStruct (StreamWriter sw) + { + sw.WriteLine ("\t\t" + IfaceName + " iface;"); + sw.WriteLine (); + sw.WriteLine ("\t\tstruct " + IfaceName + " {"); + sw.WriteLine ("\t\t\tpublic IntPtr gtype;"); + sw.WriteLine ("\t\t\tpublic IntPtr itype;"); + sw.WriteLine (); + + foreach (object member in members) { + if (member is System.String) + sw.WriteLine ("\t\t\tpublic IntPtr " + member + ";"); + else if (member is VirtualMethod) { + VirtualMethod vm = member as VirtualMethod; + sw.WriteLine ("\t\t\tpublic " + vm.Name + "Delegate " + vm.CName + ";"); + } + } + + sw.WriteLine ("\t\t}"); + sw.WriteLine (); + } + + void GenerateCtor (StreamWriter sw) + { + sw.WriteLine ("\t\tprivate " + Name + "Adapter ()"); + sw.WriteLine ("\t\t{"); + foreach (VirtualMethod vm in vms) + sw.WriteLine ("\t\t\tiface.{0} = new {1}Delegate ({1}Callback);", vm.CName, vm.Name); + sw.WriteLine ("\t\t}"); + sw.WriteLine (); + } + + void GenerateAdapterProp (StreamWriter sw) + { + sw.WriteLine ("\t\tstatic " + Name + "Adapter singleton;"); + sw.WriteLine (); + sw.WriteLine ("\t\tinternal " + Name + "Adapter Adapter {"); + sw.WriteLine ("\t\t\tget {"); + sw.WriteLine ("\t\t\t\tif (singleton == null)"); + sw.WriteLine ("\t\t\t\t\tsingleton = new " + Name + "Adapter ();"); + sw.WriteLine ("\t\t\t\treturn singleton;"); + sw.WriteLine ("\t\t\t}"); + sw.WriteLine ("\t\t}"); + sw.WriteLine (); + } + + void GenerateInitialize (StreamWriter sw) + { + sw.WriteLine ("\t\tpublic void Initialize (IntPtr ifaceptr, IntPtr data)"); + sw.WriteLine ("\t\t{"); + sw.WriteLine ("\t\t\t" + IfaceName + " iface = (" + IfaceName + ") Marshal.PtrToStructure (ifaceptr, typeof (" + IfaceName + "));"); + foreach (VirtualMethod vm in vms) + sw.WriteLine ("\t\t\tiface." + vm.CName + " = this.iface." + vm.CName + ";"); + sw.WriteLine ("\t\t\tMarshal.StructureToPtr (iface, ifaceptr, false);"); + sw.WriteLine ("\t\t}"); + } + + void GenerateCallbacks (StreamWriter sw) + { + foreach (VirtualMethod vm in vms) { + sw.WriteLine (); + vm.GenerateCallback (sw); + } + } + + void GenerateAdapter (GenerationInfo gen_info) + { + StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name + "Adapter"); + + sw.WriteLine ("namespace " + NS + " {"); + sw.WriteLine (); + sw.WriteLine ("\tusing System;"); + sw.WriteLine ("\tusing System.Runtime.InteropServices;"); + sw.WriteLine (); + sw.WriteLine ("#region Autogenerated code"); + sw.WriteLine ("\tinternal class " + Name + "Adapter : GLib.GInterfaceAdapter {"); + sw.WriteLine (); + + GenerateDelegates (sw); + GenerateIfaceStruct (sw); + GenerateCtor (sw); + GenerateAdapterProp (sw); + GenerateInitialize (sw); + GenerateCallbacks (sw); + + sw.WriteLine ("\t}"); + sw.WriteLine ("#endregion"); + sw.WriteLine ("}"); + sw.Close (); + gen_info.Writer = null; + } + + void GenSignals (GenerationInfo gen_info) + { + if (sigs.Count == 0) + return; + + StreamWriter sw = gen_info.Writer; + + sw.WriteLine (); + sw.WriteLine ("\t\t// signals"); + foreach (Signal sig in sigs.Values) { + if (sig.Validate ()) { + sig.GenerateDecl (sw); + sig.GenEventHandler (gen_info); + } else + Console.WriteLine ("of interface " + QualifiedName); + } + } + + Hashtable GenVMDecls (StreamWriter sw) + { + if (vms.Count == 0) + return new Hashtable (); + + sw.WriteLine (); + sw.WriteLine ("\t\t// virtual methods"); + Hashtable vm_decls = new Hashtable (); + foreach (VirtualMethod vm in vms) { + sw.WriteLine ("\t\t" + vm.Declaration); + vm_decls [vm.Declaration] = vm; + } + return vm_decls; + } + + void GenMethodDecls (StreamWriter sw, Hashtable vm_decls) + { + if (methods.Count == 0) + return; + + bool need_comment = true; + foreach (Method method in methods.Values) { + //if (IgnoreMethod (method)) + //continue; + + if (method.Validate ()) { + if (!vm_decls.Contains (method.Declaration) && method.Name != "GetGType") { + if (need_comment) { + sw.WriteLine (); + sw.WriteLine ("\t\t// non-virtual methods"); + need_comment = false; + } + method.GenerateDecl (sw); + } + } else + Console.WriteLine ("of interface " + QualifiedName); + } + } + + void GenerateInterface (GenerationInfo gen_info) + { + StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name); + + sw.WriteLine ("namespace " + NS + " {"); + sw.WriteLine (); + sw.WriteLine ("\tusing System;"); + sw.WriteLine (); + sw.WriteLine ("#region Autogenerated code"); + sw.WriteLine ("\tpublic interface " + Name + " : GLib.GInterface {"); + + GenSignals (gen_info); + GenMethodDecls (sw, GenVMDecls (sw)); + + AppendCustom (sw, gen_info.CustomDir); + + sw.WriteLine ("\t}"); + sw.WriteLine ("#endregion"); + sw.WriteLine ("}"); + sw.Close (); + gen_info.Writer = null; + Statistics.IFaceCount++; + } + + public void GenerateNotQuiteReadyYet (GenerationInfo gen_info) + { + ArrayList tmp = new ArrayList (); + foreach (VirtualMethod vm in vms) { + if (vm.Validate()) + tmp.Add (vm); + else { + members.Remove (vm); + Console.WriteLine ("of interface " + QualifiedName); + } + } + vms = tmp; + GenerateAdapter (gen_info); + GenerateInterface (gen_info); + } public void Generate () {