diff options
-rw-r--r-- | generator/CallbackGen.cs | 2 | ||||
-rw-r--r-- | generator/DESIGN | 99 | ||||
-rw-r--r-- | generator/EnumGen.cs | 23 | ||||
-rw-r--r-- | generator/GenBase.cs | 11 | ||||
-rw-r--r-- | generator/InterfaceGen.cs | 18 | ||||
-rw-r--r-- | generator/ObjectBase.cs | 7 | ||||
-rw-r--r-- | generator/ObjectGen.cs | 5 | ||||
-rw-r--r-- | generator/Signal.cs | 6 | ||||
-rw-r--r-- | generator/VirtualMethod.cs | 2 | ||||
-rw-r--r-- | generator/gst-codegen.diff | 526 |
10 files changed, 659 insertions, 40 deletions
diff --git a/generator/CallbackGen.cs b/generator/CallbackGen.cs index eff4cff..9bbf61b 100644 --- a/generator/CallbackGen.cs +++ b/generator/CallbackGen.cs @@ -201,7 +201,7 @@ namespace GtkSharp.Generation { sw.WriteLine ("\tusing System.Runtime.InteropServices;"); sw.WriteLine (); sw.WriteLine ("#region Autogenerated code"); - sw.WriteLine ("\t[GLib.CDeclCallback]"); + sw.WriteLine ("\t[UnmanagedFunctionPointer (CallingConvention.Cdecl)]"); sw.WriteLine ("\tinternal delegate " + retval.MarshalType + " " + wrapper + "(" + parms.ImportSignature + ");"); sw.WriteLine (); GenInvoker (gen_info, sw); diff --git a/generator/DESIGN b/generator/DESIGN new file mode 100644 index 0000000..43bd019 --- /dev/null +++ b/generator/DESIGN @@ -0,0 +1,99 @@ +Main Program +------------ + +CodeGenerator: Static class. Contains Main +GenerationInfo: Stores info passed in on the command line, such as the + assembly name and glue library name. Passed to + IGeneratable.Generate(). +Parser: Reads the foo-api.xml file and creates IGeneratable objects +Statistics: Static class. Used by other classes to keep statistics on + generated classes +SymbolTable: Static class. Keeps track of the type hierarchy and the + mappings between C types and IGeneratable classes + + +IGeneratables +------------- +The IGeneratable interface is implemented by all classes that +represent types. + +GenBase: Abstract base class for any api.xml element that will have + its own generated .cs file + + CallbackGen: Handles <callback> elements by creating a public + delegate type for the public API (in NAME.cs), and an + internal type that wraps that delegate, to be passed + as the actual unmanaged callback (in + NAMESPACESharp.NAMENative.cs) + + ClassBase: Abstract base class for types that will be converted + to C# classes, structs, or interfaces + + ClassGen: Handles <class> elements (static classes) + + HandleBase: base class for wrapped IntPtr reference types. + + OpaqueGen: Handles <boxed> and <struct> elements with the + "opaque" flag (by creating C# classes) + + ObjectBase: base class for GObject/GInterface types + + InterfaceGen: Handles <interface> elements + + ObjectGen: Handles <object> elements + + StructBase: Abstract base class for types that will be + translated to C# structs. + + BoxedGen: Handles non-opaque <boxed> elements + + StructGen: Handles non-opaque <struct> elements + + EnumGen: Handles <enum> elements. + +SimpleBase: Abstract base class for types which aren't generated from + xml like simple types or manually wrapped/implemented types. + + ByRefGen: Handles struct types that must be passed into C code by + reference (at the moment, only GValue/GLib.Value) + ManualGen: Handles types that must be manually marshalled between + managed and unmanaged code (by handwritten classes such + as GLib.List) + MarshalGen: Handles types that must be manually marshalled between + managed and unmanaged code via special CallByName/FromNative + syntax (eg time_t<->DateTime, gunichar<->char) + SimpleGen: Handles types that can be simply converted from an + unmanaged type to a managed type (int, byte, short, etc...) + LPGen : marshals system specific long and "size" types. + LPUGen : marshals system specific unsigned long and "size" types. + ConstStringGen: Handles conversion between "const char *" and + System.String + StringGen: Handles conversion between non-const "char *" and + System.String + + AliasGen: Handles <alias> elements. "Generates" type aliases by + ignoring them (eg, outputting "Gdk.Rectangle" wherever the + API calls for a GtkAllocation). + + +Other code-generating classes used by IGeneratables +--------------------------------------------------- + +Ctor: Handles <constructor> elements +Field: Handle <field> elements (only used by StructBase, not + ClassBase) +Method: Handle <method> elements +Property: Handles <property> elements + ChildProperty: Handles <childprop> elements +Signal: Handles <signal> elements + +ImportSignature: Represents a signature for an unmanaged method +ManagedCallString: Represents a call to a managed method from a + method that has unmanaged data +MethodBody: shared by Ctor and Method +Parameter: Represents the parameters to a method +SignalHandler: Used by Signal. Like CallbackGen, this creates an + internal type to wrap a signal-handler delegate. +Signature: Represents the signature of a method +VMSignature: Used by Signal. Represents the signature of a virtual + method. diff --git a/generator/EnumGen.cs b/generator/EnumGen.cs index 2be39b5..87e3810 100644 --- a/generator/EnumGen.cs +++ b/generator/EnumGen.cs @@ -24,7 +24,8 @@ namespace GtkSharp.Generation { using System;
using System.Collections;
using System.IO;
- using System.Xml;
+ using System.Xml; + using System.Text.RegularExpressions;
public class EnumGen : GenBase {
@@ -38,21 +39,21 @@ namespace GtkSharp.Generation { continue;
string result = "\t\t" + member.GetAttribute("name");
- if (member.HasAttribute("value")) {
- string value = member.GetAttribute("value");
- if (value.EndsWith("U")) {
- enum_type = " : uint";
- value = value.TrimEnd('U');
- } else if (value.EndsWith("L")) {
- enum_type = " : long";
- value = value.TrimEnd('L');
- }
+ if (member.HasAttribute ("value")) { + string value = member.GetAttribute ("value").Trim ();
+ foreach (Match match in Regex.Matches (value, "[0-9]+([UL]{1,2})", RegexOptions.IgnoreCase)) { + switch (match.Groups[1].Value.ToUpper ()) { + case "U": enum_type = " : uint"; break; + case "L": enum_type = " : long"; break; + case "UL": enum_type = " : ulong"; break; + } + } result += " = " + value;
}
members.Add (result + ",");
}
if (elem.HasAttribute ("enum_type"))
- enum_type = ": " + elem.GetAttribute ("enum_type");
+ enum_type = " : " + elem.GetAttribute ("enum_type");
}
public override bool Validate ()
diff --git a/generator/GenBase.cs b/generator/GenBase.cs index 559e3e2..ed68c5c 100644 --- a/generator/GenBase.cs +++ b/generator/GenBase.cs @@ -105,14 +105,19 @@ namespace GtkSharp.Generation { return MarshalType;
}
}
-
+ protected void AppendCustom (StreamWriter sw, string custom_dir)
+ { + AppendCustom (sw, custom_dir, Name); + } +
+ protected void AppendCustom (StreamWriter sw, string custom_dir, string type_name)
{
char sep = Path.DirectorySeparatorChar;
- string custom = custom_dir + sep + Name + ".custom";
+ string custom = custom_dir + sep + type_name + ".custom";
if (File.Exists(custom)) {
sw.WriteLine ("#region Customized extensions");
- sw.WriteLine ("#line 1 \"" + Name + ".custom\"");
+ sw.WriteLine ("#line 1 \"" + type_name + ".custom\"");
FileStream custstream = new FileStream(custom, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(custstream);
sw.WriteLine (sr.ReadToEnd ());
diff --git a/generator/InterfaceGen.cs b/generator/InterfaceGen.cs index d0dc77b..c29fa16 100644 --- a/generator/InterfaceGen.cs +++ b/generator/InterfaceGen.cs @@ -252,15 +252,7 @@ namespace GtkSharp.Generation { sw.WriteLine ("#endregion");
- string custom = Path.Combine (gen_info.CustomDir, Name + "Adapter.custom");
- if (File.Exists (custom)) {
- sw.WriteLine ("#region Customized extensions");
- sw.WriteLine ("#line 1 \"" + Name + "Adapter.custom\"");
- using (StreamReader sr = new StreamReader(new FileStream (custom, FileMode.Open, FileAccess.Read)))
- sw.WriteLine (sr.ReadToEnd ());
-
- sw.WriteLine ("#endregion");
- }
+ AppendCustom (sw, gen_info.CustomDir, Name + "Adapter");
sw.WriteLine ("\t}");
sw.WriteLine ("}");
@@ -268,8 +260,9 @@ namespace GtkSharp.Generation { gen_info.Writer = null;
}
- void GenerateImplementorIface (StreamWriter sw)
+ void GenerateImplementorIface (GenerationInfo gen_info)
{
+ StreamWriter sw = gen_info.Writer;
if (IsConsumeOnly)
return;
@@ -305,6 +298,9 @@ namespace GtkSharp.Generation { vm_table.Remove (vm.Name);
}
}
+
+ AppendCustom (sw, gen_info.CustomDir, Name + "Implementor");
+
sw.WriteLine ("\t}");
}
@@ -339,7 +335,7 @@ namespace GtkSharp.Generation { AppendCustom (sw, gen_info.CustomDir);
sw.WriteLine ("\t}");
- GenerateImplementorIface (sw);
+ GenerateImplementorIface (gen_info);
sw.WriteLine ("#endregion");
sw.WriteLine ("}");
sw.Close ();
diff --git a/generator/ObjectBase.cs b/generator/ObjectBase.cs index 7c5149e..809f0e8 100644 --- a/generator/ObjectBase.cs +++ b/generator/ObjectBase.cs @@ -154,7 +154,12 @@ namespace GtkSharp.Generation { return base.IsNodeNameHandled (name); } } - + + public virtual string CallByName (string var, bool owned) + { + return String.Format ("{0} == null ? IntPtr.Zero : ({0} as GLib.Object).{1}", var, owned ? "OwnedHandle" : "Handle"); + } + public override string FromNative (string var, bool owned) { return "GLib.Object.GetObject(" + var + (owned ? ", true" : "") + ") as " + QualifiedName; diff --git a/generator/ObjectGen.cs b/generator/ObjectGen.cs index 74a6da7..7a7d561 100644 --- a/generator/ObjectGen.cs +++ b/generator/ObjectGen.cs @@ -411,11 +411,6 @@ namespace GtkSharp.Generation { sw.WriteLine ("}");
sw.Close ();
}
-
- public string CallByName (string name, bool owned)
- {
- return name + " == null ? IntPtr.Zero : " + name + (owned ? ".OwnedHandle" : ".Handle");
- }
}
}
diff --git a/generator/Signal.cs b/generator/Signal.cs index b2ee0aa..a3be277 100644 --- a/generator/Signal.cs +++ b/generator/Signal.cs @@ -179,9 +179,9 @@ namespace GtkSharp.Generation { sw.WriteLine("\t\t\t\targs.Args[" + idx + "] = " + p.FromNative ("arg" + idx) + ";");
}
if (igen is StructBase && p.PassAs == "ref")
- finish += "\t\t\t\tif (arg" + idx + " != IntPtr.Zero) System.Runtime.InteropServices.Marshal.StructureToPtr (args.Args[" + (idx-1) + "], arg" + idx + ", false);\n";
+ finish += "\t\t\t\tif (arg" + idx + " != IntPtr.Zero) System.Runtime.InteropServices.Marshal.StructureToPtr (args.Args[" + idx + "], arg" + idx + ", false);\n";
else if (p.PassAs != "")
- finish += "\t\t\t\targ" + idx + " = " + igen.ToNativeReturn ("((" + p.CSType + ")args.Args[" + (idx - 1) + "])") + ";\n";
+ finish += "\t\t\t\targ" + idx + " = " + igen.ToNativeReturn ("((" + p.CSType + ")args.Args[" + idx + "])") + ";\n";
}
return finish;
}
@@ -219,7 +219,7 @@ namespace GtkSharp.Generation { native_signature += ", " + CallbackSig;
native_signature += ", IntPtr gch";
- sw.WriteLine ("\t\t[GLib.CDeclCallback]");
+ sw.WriteLine ("\t\t[UnmanagedFunctionPointer (CallingConvention.Cdecl)]");
sw.WriteLine ("\t\tdelegate {0} {1} ({2});", retval.ToNativeType, DelegateName, native_signature);
sw.WriteLine ();
sw.WriteLine ("\t\tstatic {0} {1} ({2})", retval.ToNativeType, CallbackName, native_signature);
diff --git a/generator/VirtualMethod.cs b/generator/VirtualMethod.cs index 670eb24..2756620 100644 --- a/generator/VirtualMethod.cs +++ b/generator/VirtualMethod.cs @@ -73,7 +73,7 @@ namespace GtkSharp.Generation { if (parms.Count > 0) native_signature += parms.ImportSignature; - sw.WriteLine ("\t\t[GLib.CDeclCallback]"); + sw.WriteLine ("\t\t[UnmanagedFunctionPointer (CallingConvention.Cdecl)]"); sw.WriteLine ("\t\tdelegate {0} {1}NativeDelegate ({2});", retval.ToNativeType, this.Name, native_signature); sw.WriteLine (); sw.WriteLine ("\t\tstatic {0} {1}_cb ({2})", retval.ToNativeType, this.Name, native_signature); diff --git a/generator/gst-codegen.diff b/generator/gst-codegen.diff index 4a4baf2..f252d0e 100644 --- a/generator/gst-codegen.diff +++ b/generator/gst-codegen.diff @@ -1,7 +1,55 @@ -Index: FieldBase.cs -=================================================================== ---- FieldBase.cs (Revision 134154) -+++ FieldBase.cs (Arbeitskopie) +diff -Naur tmp/gtk-sharp/generator/Ctor.cs generator/Ctor.cs +--- tmp/gtk-sharp/generator/Ctor.cs 2009-04-24 10:08:17.000000000 +0200 ++++ generator/Ctor.cs 2009-06-02 12:37:47.000000000 +0200 +@@ -32,14 +32,16 @@ + private bool preferred;
+ private string name;
+ private bool needs_chaining = false;
++ private bool mini_object = false; +
+ public Ctor (XmlElement elem, ClassBase implementor) : base (elem, implementor)
+ {
+ if (elem.HasAttribute ("preferred"))
+ preferred = true;
+- if (implementor is ObjectGen)
++ if (implementor is ObjectGen || implementor is MiniObjectGen)
+ needs_chaining = true;
+ name = implementor.Name;
++ mini_object = implementor is MiniObjectGen; + }
+
+ public bool Preferred {
+@@ -110,9 +112,14 @@ + sw.WriteLine ("\t\t\tif (GetType () != typeof (" + name + ")) {");
+
+ if (Parameters.Count == 0) {
+- sw.WriteLine ("\t\t\t\tCreateNativeObject (new string [0], new GLib.Value[0]);");
++ if (mini_object) ++ sw.WriteLine ("\t\t\t\tCreateNativeObject ();");
++ else ++ sw.WriteLine ("\t\t\t\tCreateNativeObject (new string [0], new GLib.Value[0]);");
+ sw.WriteLine ("\t\t\t\treturn;");
+ } else {
++ if (mini_object) ++ throw new Exception ("MiniObject subclasses can't have ctors with parameters"); + ArrayList names = new ArrayList ();
+ ArrayList values = new ArrayList ();
+ for (int i = 0; i < Parameters.Count; i++) {
+diff -Naur tmp/gtk-sharp/generator/DefaultSignalHandler.cs generator/DefaultSignalHandler.cs +--- tmp/gtk-sharp/generator/DefaultSignalHandler.cs 2009-04-13 19:44:48.000000000 +0200 ++++ generator/DefaultSignalHandler.cs 2009-06-02 12:32:24.000000000 +0200 +@@ -124,6 +124,8 @@ + + if (igen is ObjectGen) + return "GLib.GType.Object"; ++ if (igen is MiniObjectGen) ++ return "Gst.MiniObject.GType"; + if (igen is BoxedGen) + return retval.CSType + ".GType"; + if (igen is EnumGen) +diff -Naur tmp/gtk-sharp/generator/FieldBase.cs generator/FieldBase.cs +--- tmp/gtk-sharp/generator/FieldBase.cs 2009-05-06 16:58:39.000000000 +0200 ++++ generator/FieldBase.cs 2009-05-14 21:32:21.000000000 +0200 @@ -89,7 +89,7 @@ void CheckGlue () { @@ -22,3 +70,473 @@ Index: FieldBase.cs if (Getter != null) { sw.Write (indent + "\tget "); +diff -Naur tmp/gtk-sharp/generator/Makefile.am generator/Makefile.am +--- tmp/gtk-sharp/generator/Makefile.am 2009-07-23 19:18:03.000000000 +0200 ++++ generator/Makefile.am 2009-05-27 15:02:46.000000000 +0200 +@@ -1,8 +1,4 @@ +-assemblydir = $(prefix)/lib/gapi-3.0 +-assembly_DATA = gapi_codegen.exe +-bin_SCRIPTS = gapi3-codegen +-CLEANFILES = gapi_codegen.exe +-DISTCLEANFILES = gapi3-codegen ++noinst_SCRIPTS = gst-gapi_codegen.exe + + references = + +@@ -39,6 +35,7 @@ + MethodBase.cs \ + MethodBody.cs \ + Method.cs \ ++ MiniObjectGen.cs \ + ObjectField.cs \ + ObjectBase.cs \ + ObjectGen.cs \ +@@ -66,6 +63,6 @@ + EXTRA_DIST = \ + $(dist_sources) + +-gapi_codegen.exe: $(build_sources) +- $(CSC) /out:gapi_codegen.exe $(OFF_T_FLAGS) $(references) $(build_sources) ++gst-gapi_codegen.exe: $(build_sources) ++ $(CSC) -debug -out:gst-gapi_codegen.exe $(OFF_T_FLAGS) $(references) $(build_sources) + +diff -Naur tmp/gtk-sharp/generator/Method.cs generator/Method.cs +--- tmp/gtk-sharp/generator/Method.cs 2009-01-08 19:00:47.000000000 +0100 ++++ generator/Method.cs 2009-06-02 12:31:51.000000000 +0200 +@@ -118,7 +118,7 @@ +
+ if (Name == "ToString" && Parameters.Count == 0)
+ sw.Write("override ");
+- else if (Name == "GetGType" && container_type is ObjectGen)
++ else if (Name == "GetGType" && (container_type is ObjectGen || container_type is MiniObjectGen))
+ sw.Write("new ");
+ else if (Modifiers == "new " || (dup != null && ((dup.Signature != null && Signature != null && dup.Signature.ToString() == Signature.ToString()) || (dup.Signature == null && Signature == null))))
+ sw.Write("new ");
+diff -Naur tmp/gtk-sharp/generator/Parameters.cs generator/Parameters.cs +--- tmp/gtk-sharp/generator/Parameters.cs 2009-07-13 00:01:52.000000000 +0200 ++++ generator/Parameters.cs 2009-06-12 22:13:30.000000000 +0200 +@@ -262,10 +262,12 @@ + call_parm += CallName;
+ } else if (gen is IManualMarshaler)
+ call_parm = "native_" + CallName;
+- else if (gen is ObjectBase)
+- call_parm = (gen as ObjectBase).CallByName (CallName, Owned);
++ else if (gen is MiniObjectGen)
++ call_parm = ((MiniObjectGen) gen).CallByName(CallName, Owned);
++ else if (gen is ObjectGen)
++ call_parm = ((ObjectGen) gen).CallByName(CallName, Owned);
+ else
+- call_parm = gen.CallByName (CallName);
++ call_parm = gen.CallByName(CallName);
+
+ return call_parm;
+ }
+@@ -283,7 +285,7 @@ + result [i] = (gen as IManualMarshaler).ReleaseNative ("native_" + CallName) + ";";
+ return result;
+ } else if (PassAs != String.Empty && MarshalType != CSType)
+- if (gen is HandleBase)
++ if (gen is HandleBase)
+ return new string [] { CallName + " = " + (gen as HandleBase).FromNative ("native_" + CallName, Owned) + ";" };
+ else
+ return new string [] { CallName + " = " + gen.FromNative ("native_" + CallName) + ";" };
+diff -Naur tmp/gtk-sharp/generator/Parser.cs generator/Parser.cs +--- tmp/gtk-sharp/generator/Parser.cs 2009-04-13 19:44:48.000000000 +0200 ++++ generator/Parser.cs 2009-05-14 21:40:56.000000000 +0200 +@@ -138,6 +138,9 @@ + case "object":
+ result.Add (new ObjectGen (ns, elem));
+ break;
++ case "mini-object":
++ result.Add (new MiniObjectGen (ns, elem));
++ break;
+ case "class":
+ result.Add (new ClassGen (ns, elem));
+ break;
+diff -Naur tmp/gtk-sharp/generator/ReturnValue.cs generator/ReturnValue.cs +--- tmp/gtk-sharp/generator/ReturnValue.cs 2009-05-06 18:20:35.000000000 +0200 ++++ generator/ReturnValue.cs 2009-06-03 20:59:07.000000000 +0200 +@@ -110,7 +110,9 @@ + get {
+ if (IGen == null)
+ return String.Empty;
+- return IGen.ToNativeReturnType + (is_array || is_null_term ? "[]" : String.Empty);
++ else if (is_null_term)
++ return "IntPtr";
++ return IGen.ToNativeReturnType + (is_array ? "[]" : String.Empty);
+ }
+ }
+
+@@ -128,7 +130,7 @@ + } else if (IGen is HandleBase)
+ return ((HandleBase)IGen).FromNative (var, owned);
+ else if (is_null_term)
+- return String.Format ("GLib.Marshaller.NullTermPtrToStringArray ({0}, {1})", var, owned ? "true" : "false");
++ return String.Format ("Gst.Marshaller.NullTermPtrToStringArray ({0}, {1})", var, owned ? "true" : "false");
+ else
+ return IGen.FromNativeReturn (var);
+ }
+@@ -142,11 +144,11 @@ + string args = ", typeof (" + ElementType + "), " + (owned ? "true" : "false") + ", " + (elements_owned ? "true" : "false");
+ var = "new " + IGen.QualifiedName + "(" + var + args + ")";
+ } else if (is_null_term)
+- return String.Format ("GLib.Marshaller.StringArrayToNullTermPointer ({0})", var);
++ return String.Format ("Gst.Marshaller.StringArrayToNullTermPointer ({0})", var);
+
+ if (IGen is IManualMarshaler)
+ return (IGen as IManualMarshaler).AllocNative (var);
+- else if (IGen is ObjectGen && owned)
++ else if ((IGen is ObjectGen || IGen is MiniObjectGen) && owned)
+ return var + " == null ? IntPtr.Zero : " + var + ".OwnedHandle";
+ else if (IGen is OpaqueGen && owned)
+ return var + " == null ? IntPtr.Zero : " + var + ".OwnedCopy";
+diff -Naur tmp/gtk-sharp/generator/SymbolTable.cs generator/SymbolTable.cs +--- tmp/gtk-sharp/generator/SymbolTable.cs 2009-04-13 19:44:48.000000000 +0200 ++++ generator/SymbolTable.cs 2009-05-14 21:56:41.000000000 +0200 +@@ -116,6 +116,7 @@ + // manually wrapped types requiring more complex marshaling
+ AddType (new ManualGen ("GInitiallyUnowned", "GLib.InitiallyUnowned", "GLib.Object.GetObject ({0})"));
+ AddType (new ManualGen ("GObject", "GLib.Object", "GLib.Object.GetObject ({0})"));
++ AddType (new ManualGen ("GstMiniObject", "Gst.MiniObject", "Gst.MiniObject.GetObject ({0})"));
+ AddType (new ManualGen ("GList", "GLib.List"));
+ AddType (new ManualGen ("GPtrArray", "GLib.PtrArray"));
+ AddType (new ManualGen ("GSList", "GLib.SList"));
+@@ -338,7 +339,8 @@ +
+ public bool IsObject(string c_type)
+ {
+- if (this[c_type] is ObjectGen)
++ if ((this[c_type] is ObjectGen) ||
++ (this[c_type] is MiniObjectGen))
+ return true;
+
+ return false;
+--- /dev/null 2009-07-17 07:52:05.502147313 +0200 ++++ generator/MiniObjectGen.cs 2009-06-12 22:11:07.000000000 +0200 +@@ -0,0 +1,326 @@ ++// GtkSharp.Generation.MiniObjectGen.cs - The Mini Object Generatable.
++//
++// Author: Mike Kestner <mkestner@ximian.com>
++//
++// Copyright (c) 2001-2003 Mike Kestner
++// Copyright (c) 2003-2004 Novell, Inc.
++// Copyright (c) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
++//
++// This program is free software; you can redistribute it and/or
++// modify it under the terms of version 2 of the GNU General Public
++// License as published by the Free Software Foundation.
++//
++// This program is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++// General Public License for more details.
++//
++// You should have received a copy of the GNU General Public
++// License along with this program; if not, write to the
++// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++// Boston, MA 02111-1307, USA.
++
++
++namespace GtkSharp.Generation {
++
++ using System;
++ using System.Collections;
++ using System.IO;
++ using System.Text;
++ using System.Xml;
++
++ public class MiniObjectGen : ObjectBase {
++
++ private ArrayList custom_attrs = new ArrayList();
++ private ArrayList strings = new ArrayList();
++ private static Hashtable dirs = new Hashtable ();
++
++ public MiniObjectGen (XmlElement ns, XmlElement elem) : base (ns, elem, false)
++ {
++ foreach (XmlNode node in elem.ChildNodes) {
++ if (!(node is XmlElement)) continue;
++ XmlElement member = (XmlElement) node;
++ if (member.HasAttribute ("hidden") && member.GetAttribute ("hidden") == "1") continue;
++
++ switch (node.Name) {
++ case "custom-attribute":
++ custom_attrs.Add (member.InnerXml);
++ break;
++
++ case "static-string":
++ strings.Add (node);
++ break;
++
++ default:
++ if (!IsNodeNameHandled (node.Name))
++ Console.WriteLine ("Unexpected node " + node.Name + " in " + CName);
++ break;
++ }
++ }
++ }
++
++ public override bool Validate ()
++ {
++ ArrayList invalids = new ArrayList ();
++
++ return base.Validate ();
++ }
++
++ private bool DisableVoidCtor {
++ get {
++ return Elem.HasAttribute ("disable_void_ctor");
++ }
++ }
++
++ private bool DisableGTypeCtor {
++ get {
++ return Elem.HasAttribute ("disable_gtype_ctor");
++ }
++ }
++
++ private class DirectoryInfo {
++ public string assembly_name;
++ public Hashtable objects;
++
++ public DirectoryInfo (string assembly_name) {
++ this.assembly_name = assembly_name;
++ objects = new Hashtable ();
++ }
++ }
++
++ private static DirectoryInfo GetDirectoryInfo (string dir, string assembly_name)
++ {
++ DirectoryInfo result;
++
++ if (dirs.ContainsKey (dir)) {
++ result = dirs [dir] as DirectoryInfo;
++ if (result.assembly_name != assembly_name) {
++ Console.WriteLine ("Can't put multiple assemblies in one directory.");
++ return null;
++ }
++
++ return result;
++ }
++
++ result = new DirectoryInfo (assembly_name);
++ dirs.Add (dir, result);
++
++ return result;
++ }
++
++ public override void Generate (GenerationInfo gen_info)
++ {
++ gen_info.CurrentType = Name;
++
++ string asm_name = gen_info.AssemblyName.Length == 0 ? NS.ToLower () + "-sharp" : gen_info.AssemblyName;
++ DirectoryInfo di = GetDirectoryInfo (gen_info.Dir, asm_name);
++
++ StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name);
++
++ sw.WriteLine ("namespace " + NS + " {");
++ sw.WriteLine ();
++ sw.WriteLine ("\tusing System;");
++ sw.WriteLine ("\tusing System.Collections;");
++ sw.WriteLine ("\tusing System.Runtime.InteropServices;");
++ sw.WriteLine ();
++
++ SymbolTable table = SymbolTable.Table;
++
++ sw.WriteLine ("#region Autogenerated code");
++ if (IsDeprecated)
++ sw.WriteLine ("\t[Obsolete]");
++ foreach (string attr in custom_attrs)
++ sw.WriteLine ("\t" + attr);
++ sw.Write ("\t{0} {1}class " + Name, IsInternal ? "internal" : "public", IsAbstract ? "abstract " : "");
++ string cs_parent = table.GetCSType(Elem.GetAttribute("parent"));
++ if (cs_parent != "") {
++ di.objects.Add (CName, QualifiedName);
++ sw.Write (" : " + cs_parent);
++ }
++ foreach (string iface in managed_interfaces) {
++ if (Parent != null && Parent.Implements (iface))
++ continue;
++ sw.Write (", " + iface);
++ }
++ sw.WriteLine (" {");
++ sw.WriteLine ();
++
++ GenCtors (gen_info);
++ GenFields (gen_info);
++
++ GenClassMembers (gen_info, cs_parent);
++ GenMethods (gen_info, null, null);
++
++ foreach (XmlElement str in strings) {
++ sw.Write ("\t\tpublic static string " + str.GetAttribute ("name"));
++ sw.WriteLine (" {\n\t\t\t get { return \"" + str.GetAttribute ("value") + "\"; }\n\t\t}");
++ }
++
++ if (cs_parent != String.Empty && GetExpected (CName) != QualifiedName) {
++ sw.WriteLine ();
++ sw.WriteLine ("\t\tstatic " + Name + " ()");
++ sw.WriteLine ("\t\t{");
++ sw.WriteLine ("\t\t\tGtkSharp." + Studlify (asm_name) + ".ObjectManager.Initialize ();");
++ sw.WriteLine ("\t\t}");
++ }
++
++ sw.WriteLine ("#endregion");
++ AppendCustom (sw, gen_info.CustomDir);
++
++ sw.WriteLine ("\t}");
++ sw.WriteLine ("}");
++
++ sw.Close ();
++ gen_info.Writer = null;
++ Statistics.ObjectCount++;
++ }
++
++ protected override void GenCtors (GenerationInfo gen_info)
++ {
++ if (!Elem.HasAttribute("parent"))
++ return;
++
++ if (!DisableGTypeCtor) {
++ gen_info.Writer.WriteLine("\t\t[Obsolete]");
++ gen_info.Writer.WriteLine("\t\tprotected " + Name + "(GLib.GType gtype) : base(gtype) {}");
++ }
++ gen_info.Writer.WriteLine("\t\tpublic " + Name + "(IntPtr raw) : base(raw) {}");
++ if (ctors.Count == 0 && !DisableVoidCtor) {
++ gen_info.Writer.WriteLine();
++ gen_info.Writer.WriteLine("\t\tprotected " + Name + "() : base(IntPtr.Zero)");
++ gen_info.Writer.WriteLine("\t\t{");
++ gen_info.Writer.WriteLine("\t\t\tCreateNativeObject ();");
++ gen_info.Writer.WriteLine("\t\t}");
++ }
++ gen_info.Writer.WriteLine();
++
++ base.GenCtors (gen_info);
++ }
++
++ void GenClassMembers (GenerationInfo gen_info, string cs_parent)
++ {
++ GenVirtualMethods (gen_info, null);
++
++ if (class_struct_name == null || !CanGenerateClassStruct) return;
++ StreamWriter sw = gen_info.Writer;
++ GenerateClassStruct (gen_info);
++ if (cs_parent == "")
++ sw.WriteLine ("\t\tstatic uint class_offset = 0;");
++ else
++ sw.WriteLine ("\t\tstatic uint class_offset = ((GLib.GType) typeof ({0})).ClassSize;", cs_parent);
++ sw.WriteLine ("\t\tstatic Hashtable class_structs;");
++ sw.WriteLine ();
++ sw.WriteLine ("\t\tstatic {0} GetClassStruct (GLib.GType gtype, bool use_cache)", class_struct_name);
++ sw.WriteLine ("\t\t{");
++ sw.WriteLine ("\t\t\tif (class_structs == null)");
++ sw.WriteLine ("\t\t\t\tclass_structs = new Hashtable ();");
++ sw.WriteLine ();
++ sw.WriteLine ("\t\t\tif (use_cache && class_structs.Contains (gtype))");
++ sw.WriteLine ("\t\t\t\treturn ({0}) class_structs [gtype];", class_struct_name);
++ sw.WriteLine ("\t\t\telse {");
++ sw.WriteLine ("\t\t\t\tIntPtr class_ptr = new IntPtr (gtype.ClassPtr.ToInt64 () + class_offset);");
++ sw.WriteLine ("\t\t\t\t{0} class_struct = ({0}) Marshal.PtrToStructure (class_ptr, typeof ({0}));", class_struct_name);
++ sw.WriteLine ("\t\t\t\tif (use_cache)");
++ sw.WriteLine ("\t\t\t\t\tclass_structs.Add (gtype, class_struct);");
++ sw.WriteLine ("\t\t\t\treturn class_struct;");
++ sw.WriteLine ("\t\t\t}");
++ sw.WriteLine ("\t\t}");
++ sw.WriteLine ();
++ sw.WriteLine ("\t\tstatic void OverrideClassStruct (GLib.GType gtype, {0} class_struct)", class_struct_name);
++ sw.WriteLine ("\t\t{");
++ sw.WriteLine ("\t\t\tIntPtr class_ptr = new IntPtr (gtype.ClassPtr.ToInt64 () + class_offset);");
++ sw.WriteLine ("\t\t\tMarshal.StructureToPtr (class_struct, class_ptr, false);");
++ sw.WriteLine ("\t\t}");
++ sw.WriteLine ();
++ }
++
++ /* Keep this in sync with the one in glib/GType.cs */
++ private static string GetExpected (string cname)
++ {
++ for (int i = 1; i < cname.Length; i++) {
++ if (Char.IsUpper (cname[i])) {
++ if (i == 1 && cname[0] == 'G')
++ return "GLib." + cname.Substring (1);
++ else
++ return cname.Substring (0, i) + "." + cname.Substring (i);
++ }
++ }
++
++ throw new ArgumentException ("cname doesn't follow the NamespaceType capitalization style: " + cname);
++ }
++
++ private static bool NeedsMap (Hashtable objs, string assembly_name)
++ {
++ foreach (string key in objs.Keys)
++ if (GetExpected (key) != ((string) objs[key]))
++ return true;
++
++ return false;
++ }
++
++ private static string Studlify (string name)
++ {
++ string result = "";
++
++ string[] subs = name.Split ('-');
++ foreach (string sub in subs)
++ result += Char.ToUpper (sub[0]) + sub.Substring (1);
++
++ return result;
++ }
++
++ public static void GenerateMappers ()
++ {
++ foreach (string dir in dirs.Keys) {
++
++ DirectoryInfo di = dirs[dir] as DirectoryInfo;
++
++ if (!NeedsMap (di.objects, di.assembly_name))
++ continue;
++
++ GenerationInfo gen_info = new GenerationInfo (dir, di.assembly_name);
++
++ GenerateMapper (di, gen_info);
++ }
++ }
++
++ private static void GenerateMapper (DirectoryInfo dir_info, GenerationInfo gen_info)
++ {
++ StreamWriter sw = gen_info.OpenStream ("ObjectManager");
++
++ sw.WriteLine ("namespace GtkSharp." + Studlify (dir_info.assembly_name) + " {");
++ sw.WriteLine ();
++ sw.WriteLine ("\tpublic class ObjectManager {");
++ sw.WriteLine ();
++ sw.WriteLine ("\t\tstatic bool initialized = false;");
++ sw.WriteLine ("\t\t// Call this method from the appropriate module init function.");
++ sw.WriteLine ("\t\tpublic static void Initialize ()");
++ sw.WriteLine ("\t\t{");
++ sw.WriteLine ("\t\t\tif (initialized)");
++ sw.WriteLine ("\t\t\t\treturn;");
++ sw.WriteLine ("");
++ sw.WriteLine ("\t\t\tinitialized = true;");
++
++ foreach (string key in dir_info.objects.Keys) {
++ if (GetExpected(key) != ((string) dir_info.objects[key]))
++ sw.WriteLine ("\t\t\tGLib.GType.Register ({0}.GType, typeof ({0}));", dir_info.objects [key]);
++ }
++
++ sw.WriteLine ("\t\t}");
++ sw.WriteLine ("\t}");
++ sw.WriteLine ("}");
++ sw.Close ();
++ }
++
++ public string CallByName (string name, bool owned)
++ {
++ return name + " == null ? IntPtr.Zero : " + name + (owned ? ".OwnedHandle" : ".Handle");
++ }
++
++ public override string FromNative (string var, bool owned)
++ {
++ return "Gst.MiniObject.GetObject(" + var + (owned ? ", true" : "") + ") as " + QualifiedName;
++ }
++ }
++}
++
|