diff --git a/ChangeLog b/ChangeLog index 393d22c72..0ed0491c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2002-02-02 Mike Kestner + + * generator/ObjectGen.cs : Add IntPtr constructor generation. Pass a + ctor signature hash around to use in clash resolution. Generate a + void ctor if none is present which just calls the parent ctor. + * generator/StructBase.cs : Add non-void signature ctor generation, + including collision handling logic. Collisions are implemented as + static methods. + * generator/SymbolTable.cs : Map GSList to GLib.SList. Add type + trimming to remove trailing *'s. Need to suppress leading const yet. + * glib/Object.cs : Add default ctor for void and IntPtr ctors. + * glib/SList.cs : Implementation of a wrapper class for GSLists. Lots + of FIXMEs. + * parser/gapi2xml.pl : Handle ** and array params. + 2002-01-17 Mike Kestner * generator/BoxedGen.cs : Removed Name, CName, and QualifiedName. diff --git a/generator/ObjectGen.cs b/generator/ObjectGen.cs index ba4211e0a..3690b0bf8 100644 --- a/generator/ObjectGen.cs +++ b/generator/ObjectGen.cs @@ -7,6 +7,7 @@ namespace GtkSharp.Generation { using System; + using System.Collections; using System.IO; using System.Xml; @@ -59,6 +60,11 @@ namespace GtkSharp.Generation { } sw.WriteLine (); + sw.WriteLine("\t\tpublic " + Name + "(IntPtr raw) : base(raw) {}"); + sw.WriteLine(); + + Hashtable clash_map = new Hashtable(); + foreach (XmlNode node in elem.ChildNodes) { XmlElement member = (XmlElement) node; @@ -74,7 +80,7 @@ namespace GtkSharp.Generation { break; case "constructor": - if (!GenCtor(member, table, sw)) { + if (!GenCtor(member, table, sw, clash_map)) { Console.WriteLine("in object " + CName); } break; @@ -97,6 +103,11 @@ namespace GtkSharp.Generation { } } + + if (!clash_map.ContainsKey("")) { + sw.WriteLine("\t\tpublic " + Name + "() : base(){}"); + sw.WriteLine(); + } sw.WriteLine ("\t}"); sw.WriteLine (); diff --git a/generator/StructBase.cs b/generator/StructBase.cs index af2eee32a..581b61cfe 100644 --- a/generator/StructBase.cs +++ b/generator/StructBase.cs @@ -7,7 +7,9 @@ namespace GtkSharp.Generation { using System; + using System.Collections; using System.IO; + using System.Text.RegularExpressions; using System.Xml; public class StructBase { @@ -43,33 +45,48 @@ namespace GtkSharp.Generation { } - protected bool GenCtor(XmlElement ctor, SymbolTable table, StreamWriter sw) + protected bool GenCtor(XmlElement ctor, SymbolTable table, StreamWriter sw, Hashtable clash_map) { - String sig, isig, call; + String sig, isig, call, sigtypes; XmlElement parms = ctor["parameters"]; if (parms == null) { sig = "()"; isig = call = "();"; - //} else if (!GetSignature(parms, table, out sig) || - // !GetImportSig(parms, table, out isig) || - // !GetCallString(parms, table, out call)) { - // Console.Write("ctor "); - // return false; - } else { - Console.Write("ctor with parms "); - return false; + sigtypes = ""; + } else if (!GetSignature(parms, table, out sig, out sigtypes) || + !GetImportSig(parms, table, out isig) || + !GetCallString(parms, table, out call)) { + Console.Write("ctor "); + return false; } + bool clash = false; + if (clash_map.ContainsKey(sigtypes)) { + clash = true; + } else { + clash_map[sigtypes] = ctor; + } + String cname = ctor.GetAttribute("cname"); sw.WriteLine("\t\t[DllImport(\"" + table.GetDllName(ns) + "\", CallingConvention=CallingConvention.Cdecl)]"); sw.WriteLine("\t\tstatic extern IntPtr " + cname + isig); sw.WriteLine(); - sw.WriteLine("\t\tpublic " + Name + sig); - sw.WriteLine("\t\t{"); - sw.WriteLine("\t\t\tRawObject = " + cname + call); + + if (clash) { + String mname = cname.Substring(cname.IndexOf("new")); + // mname = Regex.Replace(mname, "_(\\w)", "\\u\\1"); + sw.WriteLine("\t\tpublic static " + Name + " " + mname + sig); + sw.WriteLine("\t\t{"); + sw.WriteLine("\t\t\treturn new " + Name + "(" + cname + call + ");"); + } else { + sw.WriteLine("\t\tpublic " + Name + sig); + sw.WriteLine("\t\t{"); + sw.WriteLine("\t\t\tRawObject = " + cname + call + ";"); + } + sw.WriteLine("\t\t}"); sw.WriteLine(); @@ -106,6 +123,8 @@ namespace GtkSharp.Generation { { call = "("; + bool need_comma = false; + foreach (XmlNode parm in parms.ChildNodes) { if (parm.Name != "parameter") { continue; @@ -114,7 +133,7 @@ namespace GtkSharp.Generation { XmlElement elem = (XmlElement) parm; } - call += ");"; + call += ")"; return true; } @@ -134,21 +153,55 @@ namespace GtkSharp.Generation { return true; } - private bool GetSignature(XmlElement parms, SymbolTable table, out String sig) + private bool GetSignature(XmlElement parms, SymbolTable table, out String sig, out String sigtypes) { sig = "("; + bool need_comma = false; + sigtypes = ""; + foreach (XmlNode parm in parms.ChildNodes) { if (parm.Name != "parameter") { continue; } XmlElement elem = (XmlElement) parm; + String type = elem.GetAttribute("type"); + String cs_type = table.GetCSType(type); + String name = elem.GetAttribute("name"); + name = MangleName(name); + + if ((cs_type == "") || (name == "")) { + Console.Write("Name: " + name + " Type: " + type + " "); + return false; + } + + if (elem.HasAttribute("array")) { + cs_type += "[]"; + } + + if (need_comma) { + sig += ", "; + sigtypes += ":"; + } else { + need_comma = true; + } + sig += (cs_type + " " + name); + sigtypes += cs_type; } sig += ")"; return true; } + + private String MangleName(String name) + { + if (name == "string") { + return "str1ng"; + } else { + return name; + } + } } } diff --git a/generator/SymbolTable.cs b/generator/SymbolTable.cs index e5d3d0c58..fe6109ddf 100644 --- a/generator/SymbolTable.cs +++ b/generator/SymbolTable.cs @@ -59,7 +59,7 @@ namespace GtkSharp.Generation { simple_types.Add ("GArray", "IntPtr"); simple_types.Add ("GData", "IntPtr"); simple_types.Add ("GTypeModule", "GLib.Object"); - simple_types.Add ("GSList", "IntPtr"); + simple_types.Add ("GSList", "GLib.SList"); simple_types.Add ("GHashTable", "IntPtr"); simple_types.Add ("va_list", "IntPtr"); simple_types.Add ("GParamSpec", "IntPtr"); @@ -88,8 +88,16 @@ namespace GtkSharp.Generation { return complex_types.GetEnumerator(); } + private String Trim(String type) + { + char[] ast = {'*'}; + String trim_type = type.TrimEnd(ast); + return trim_type; + } + public String GetCSType(String c_type) { + c_type = Trim(c_type); if (simple_types.ContainsKey(c_type)) { return (String) simple_types[c_type]; } else if (complex_types.ContainsKey(c_type)) { diff --git a/generator/api.xml b/generator/api.xml index 38236ffa3..a9117f82c 100644 --- a/generator/api.xml +++ b/generator/api.xml @@ -1,2 +1,2 @@ - + diff --git a/glib/Object.cs b/glib/Object.cs index af20cf83e..e908a91f7 100644 --- a/glib/Object.cs +++ b/glib/Object.cs @@ -51,6 +51,28 @@ namespace GLib { return null; //FIXME: Call TypeParser here eventually. } + /// + /// Object Constructor + /// + /// + /// + /// Dummy constructor needed for derived classes. + /// + + public Object () {} + + /// + /// Object Constructor + /// + /// + /// + /// Creates an object from a raw object reference. + /// + + public Object (IntPtr raw) + { + RawObject = raw; + } /// /// RawObject Property diff --git a/glib/SList.cs b/glib/SList.cs new file mode 100644 index 000000000..ee974881c --- /dev/null +++ b/glib/SList.cs @@ -0,0 +1,316 @@ +// SList.cs - GSList class wrapper implementation +// +// Authors: Mike Kestner +// +// (c) 2002 Mike Kestner + +namespace GLib { + + using System; + using System.Collections; + using System.Runtime.InteropServices; + + /// + /// SList Class + /// + /// + /// + /// Wrapper class for GSList. + /// + + public class SList : IList { + + // Private class and instance members + IntPtr _list; + int rev_cnt; + + /// + /// Object Constructor + /// + /// + /// + /// Dummy constructor needed for derived classes. + /// + + public SList () + { + _list = IntPtr.Zero; + rev_cnt = 0; + } + + /// + /// Handle Property + /// + /// + /// + /// The raw GSList reference. There should be no need to + /// use this other than marshaling situations. + /// + + public IntPtr Handle { + get { + return _list; + } + } + + // ------------------------------ + // ICollection Interface Implementation + // ------------------------------ + + /// + /// Count Property + /// + /// + /// + /// The number of elements in the SList. + /// + + [DllImport("glib-1.3.dll", CallingConvention=CallingConvention.Cdecl)] + static extern int g_slist_length(IntPtr raw); + + public int Count { + get { + return g_slist_length(_list); + } + } + + /// + /// IsSynchronized Property + /// + /// + /// + /// Returns false. GSLists are not threadsafe. + /// + + public bool IsSynchronized { + get { + return false; + } + } + + /// + /// SyncRoot Property + /// + /// + /// + /// Throws not implemented exception. GSLists are not + /// thread safe. + /// + + public object SyncRoot { + get { + throw new NotImplementedException(); + } + } + + /// + /// CopyTo Method + /// + /// + /// + /// Copies the list to an Array. + /// + + public void CopyTo(Array target, int index) + { + foreach (IntPtr item in this) { + target.SetValue(item, index++); + } + } + + // ------------------------------ + // IEnumerable Interface Implementation + // ------------------------------ + + public IEnumerator GetEnumerator() + { + return new SListEnumerator(this); + } + + // ------------------------------ + // IList Interface Implementation + // ------------------------------ + + /// + /// IsFixedSize Property + /// + /// + /// + /// Returns false. Items can be added and removed from + /// an SList. + /// + + public bool IsFixedSize { + get { + return false; + } + } + + /// + /// IsReadOnly Property + /// + /// + /// + /// Returns false. Items of an SList can be modified. + /// + + public bool IsReadOnly { + get { + return false; + } + } + + /// + /// Item Property + /// + /// + /// + /// Indexer to access members of the SList. + /// + + [DllImport("glib-1.3.dll", CallingConvention=CallingConvention.Cdecl)] + static extern IntPtr g_slist_nth_data(IntPtr raw, int index); + + public object this[int index] { + get { + return g_slist_nth_data(_list, index); + } + set { + // FIXME: Set a data element. + rev_cnt++; + } + } + + // FIXME: Just a stub + public int Add(object o) + { + rev_cnt++; + return 0; + } + + // FIXME: Just a stub + public void Clear() + { + rev_cnt++; + } + + // FIXME: Just a stub + public bool Contains(object o) + { + return false; + } + + // FIXME: Just a stub + public int IndexOf(object o) + { + return 0; + } + + // FIXME: Just a stub + public void Insert(int index, object o) + { + rev_cnt++; + } + + // FIXME: Just a stub + public void Remove(object o) + { + rev_cnt++; + } + + // FIXME: Just a stub + public void RemoveAt(int index) + { + rev_cnt++; + } + + // -------------- + // object methods + // -------------- + + /// + /// Equals Method + /// + /// + /// + /// Checks equivalence of two SLists. + /// + + public override bool Equals (object o) + { + if (!(o is SList)) + return false; + + return (Handle == ((SList) o).Handle); + } + + /// + /// GetHashCode Method + /// + /// + /// + /// Calculates a hashing value. + /// + + public override int GetHashCode () + { + return Handle.GetHashCode (); + } + + // Internal enumerator class + + public class SListEnumerator : IEnumerator { + + IntPtr _cursor; + int i_rev; + SList _list; + bool virgin; + + public SListEnumerator (SList list) + { + _list = list; + i_rev = list.rev_cnt; + virgin = true; + } + + public object Current { + get { + if (virgin || (i_rev != _list.rev_cnt)) { + throw new InvalidOperationException(); + } + + if (_cursor == IntPtr.Zero) { + return null; + } + + return Marshal.ReadIntPtr(_cursor); + } + } + + public bool MoveNext() + { + if (i_rev != _list.rev_cnt) { + throw new InvalidOperationException(); + } + + if (virgin) { + _cursor = _list.Handle; + } else if (_cursor != IntPtr.Zero) { + _cursor = Marshal.ReadIntPtr(_cursor, IntPtr.Size); + } + + return (_cursor != IntPtr.Zero); + } + + public void Reset() + { + if (i_rev != _list.rev_cnt) { + throw new InvalidOperationException(); + } + + virgin = true; + } + } + + } +} diff --git a/parser/gapi2xml.pl b/parser/gapi2xml.pl index aed678e25..771296102 100755 --- a/parser/gapi2xml.pl +++ b/parser/gapi2xml.pl @@ -418,11 +418,16 @@ sub addParamsElem foreach $parm (@params) { $parm_elem = $doc->createElement('parameter'); $parms_elem->appendChild($parm_elem); - $parm =~ s/\s+\*/\* /g; + $parm =~ s/\s+(\*+)/\1 /g; $parm =~ s/const\s+/const-/g; $parm =~ /(\S+)\s+(\S+)/; - $parm_elem->setAttribute('type', "$1"); - $parm_elem->setAttribute('name', "$2"); + $parm_elem->setAttribute('type', $1); + my $name = $2; + if ($name =~ /(\w+)\[\]/) { + $name = $1; + $parm_elem->setAttribute('array', "true"); + } + $parm_elem->setAttribute('name', $name); } }