Ryujinx-GtkSharp/generator/InterfaceGen.cs
Dan Winship 85d88fe1ca Change the way generatable validation works. Some generatable
properties can't be set until Validate-time (eg, Method.IsGetter),
	but it's annoying for every potential user of those properties to
	have to make sure it has Validated the generatable first. So now
	we add an explicit Validate() step after everything is loaded but
	before anything is Generated, so that at Generation time,
	everything can be assumed to have been Validated.

	* generator/IGeneratable.cs: add "bool Validate()"

	* generator/CodeGenerator.cs (Main): after loading all of the
	generatables, DeAlias the SymbolTable, Validate() all the
	generatables, and discard any invalid ones.

	* generator/*.cs: Implement Validate() trivially in generatables
	that didn't implement it before. Move Validate() calls from
	Generate() to Validate(). Remove non-hierarchical Validate()
	calls.

	* generator/SymbolTable.cs: GPtrArray is IntPtr, not IntPtr[]

svn path=/trunk/gtk-sharp/; revision=48046
2005-08-05 20:34:45 +00:00

293 lines
8.0 KiB
C#

// GtkSharp.Generation.InterfaceGen.cs - The Interface Generatable.
//
// Author: Mike Kestner <mkestner@speakeasy.net>
//
// 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
// 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.Xml;
public class InterfaceGen : ObjectBase {
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) {
sig.GenerateDecl (sw);
sig.GenEventHandler (gen_info);
}
}
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 (!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);
}
}
}
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 override void Generate (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.IWrapper {");
sw.WriteLine ();
foreach (Signal sig in sigs.Values) {
sig.GenerateDecl (sw);
sig.GenEventHandler (gen_info);
}
foreach (Method method in methods.Values) {
if (IgnoreMethod (method))
continue;
method.GenerateDecl (sw);
}
foreach (Property prop in props.Values)
prop.GenerateDecl (sw, "\t\t");
AppendCustom (sw, gen_info.CustomDir);
sw.WriteLine ("\t}");
sw.WriteLine ("#endregion");
sw.WriteLine ("}");
sw.Close ();
gen_info.Writer = null;
Statistics.IFaceCount++;
}
}
}