Ryujinx-GtkSharp/generator/GenerationInfo.cs
Mike Kestner 39ac15b6b6 2008-05-02 Mike Kestner <mkestner@novell.com>
* generator/GenerationInfo.cs:  refactor glue writer implementation
	so that GlueEnabled means there is a valid glue writer available.
	Avoids crashes in scenarios where an unwriteable glue path is provided
	to the generator.  Generate a glue function which scans the type
	hierarchy of an object for the most-derived unmanaged ancestor so
	that we can invoke class methods on it, avoiding infinite recursions.
	* generator/Signal.cs: revamp the default handler vm overriding 
	mechanism.  When class fields exist which can be directly hooked into,
	we now generate glue to override and chain up to unmanaged base funcs.
	This avoids some strangeness in the g_signal_override_class_closure
	and g_signal_chain_from_overridden reported in #332300 and also lays
	the groundwork for automated generation of non-signal VMs.
	* gtk/Gtk.metadata: block signal glue generation for a few types which 
	don't seem to install headers.

svn path=/trunk/gtk-sharp/; revision=102350
2008-05-02 17:10:05 +00:00

189 lines
5.0 KiB
C#

// GtkSharp.Generation.GenerationInfo.cs - Generation information class.
//
// Author: Mike Kestner <mkestner@ximian.com>
//
// Copyright (c) 2003-2008 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 GenerationInfo {
string dir;
string custom_dir;
string assembly_name;
string gluelib_name;
bool glue_enabled;
StreamWriter sw;
StreamWriter glue_sw;
public GenerationInfo (XmlElement ns)
{
string ns_name = ns.GetAttribute ("name");
char sep = Path.DirectorySeparatorChar;
dir = ".." + sep + ns_name.ToLower () + sep + "generated";
custom_dir = ".." + sep + ns_name.ToLower ();
assembly_name = ns_name.ToLower () + "-sharp";
}
public GenerationInfo (string dir, string assembly_name) : this (dir, dir, assembly_name, "", "", "") {}
public GenerationInfo (string dir, string custom_dir, string assembly_name, string glue_filename, string glue_includes, string gluelib_name)
{
this.dir = dir;
this.custom_dir = custom_dir;
this.assembly_name = assembly_name;
this.gluelib_name = gluelib_name;
InitializeGlue (glue_filename, glue_includes, gluelib_name);
}
void InitializeGlue (string glue_filename, string glue_includes, string gluelib_name)
{
if (gluelib_name != String.Empty && glue_filename != String.Empty) {
FileStream stream;
try {
stream = new FileStream (glue_filename, FileMode.Create, FileAccess.Write);
} catch (Exception) {
Console.Error.WriteLine ("Unable to create specified glue file. Glue will not be generated.");
return;
}
glue_sw = new StreamWriter (stream);
glue_sw.WriteLine ("// This file was generated by the Gtk# code generator.");
glue_sw.WriteLine ("// Any changes made will be lost if regenerated.");
glue_sw.WriteLine ();
if (glue_includes != "") {
foreach (string header in glue_includes.Split (new char[] {',', ' '})) {
if (header != "")
glue_sw.WriteLine ("#include <{0}>", header);
}
glue_sw.WriteLine ("");
}
glue_sw.WriteLine ("const gchar *__prefix = \"__gtksharp_\";\n");
glue_sw.WriteLine ("#define HAS_PREFIX(a) (*((guint64 *)(a)) == *((guint64 *) __prefix))\n");
glue_sw.WriteLine ("static GObjectClass *");
glue_sw.WriteLine ("get_threshold_class (GObject *obj)");
glue_sw.WriteLine ("{");
glue_sw.WriteLine ("\tGType gtype = G_TYPE_FROM_INSTANCE (obj);");
glue_sw.WriteLine ("\twhile (HAS_PREFIX (g_type_name (gtype)))");
glue_sw.WriteLine ("\t\tgtype = g_type_parent (gtype);");
glue_sw.WriteLine ("\tGObjectClass *klass = g_type_class_peek (gtype);");
glue_sw.WriteLine ("\tif (klass == NULL) klass = g_type_class_ref (gtype);");
glue_sw.WriteLine ("\treturn klass;");
glue_sw.WriteLine ("}\n");
glue_enabled = true;
}
}
public string AssemblyName {
get {
return assembly_name;
}
}
public string CustomDir {
get {
return custom_dir;
}
}
public string Dir {
get {
return dir;
}
}
public string GluelibName {
get {
return gluelib_name;
}
}
public bool GlueEnabled {
get {
return glue_enabled;
}
}
public StreamWriter GlueWriter {
get {
return glue_sw;
}
}
public StreamWriter Writer {
get {
return sw;
}
set {
sw = value;
}
}
public void CloseGlueWriter ()
{
if (glue_sw != null)
glue_sw.Close ();
}
string member;
public string CurrentMember {
get {
return typename + "." + member;
}
set {
member = value;
}
}
string typename;
public string CurrentType {
get {
return typename;
}
set {
typename = value;
}
}
public StreamWriter OpenStream (string name)
{
char sep = Path.DirectorySeparatorChar;
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
string filename = dir + sep + name + ".cs";
FileStream stream = new FileStream (filename, FileMode.Create, FileAccess.Write);
StreamWriter sw = new StreamWriter (stream);
sw.WriteLine ("// This file was generated by the Gtk# code generator.");
sw.WriteLine ("// Any changes made will be lost if regenerated.");
sw.WriteLine ();
return sw;
}
}
}