2002-06-09 Rachel Hestilow <hestilow@ximian.com>
* generator/GenBase.cs: new method AppendCustom, moved from ObjectGen. * generator/BoxedGen.cs, ObjectGen.cs, StructGen.cs: Call AppendCustom in Generate (); * generator/Method.cs, Parameters.cs: Add support for "out" parameters. Additionally, output an accessor instead of a regular method if it is an accessor-style function (ie GetStartIter). * generator/Property.cs: Add additional cast to Boxed, if necessary. * glue/textiter.c: New constructor for GtkTextIter. * glue/Makefile.am: Add textiter.c, build with Gtk+ cflags. * configure.in: Check for Gtk+ cflags. * parser/Metadata.pm, Gtk.metadata: Added. * parser/gapi2xml.pl: Call Metadata::fixup on the document. Also work around gtk's screwy boxed type name registration (GtkFoo -> GtkTypeFoo). * gtk/TextIter.custom: Added. svn path=/trunk/gtk-sharp/; revision=5205
This commit is contained in:
parent
63624a886d
commit
eea6465cf2
19 changed files with 660 additions and 29 deletions
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
|||
2002-06-09 Rachel Hestilow <hestilow@ximian.com>
|
||||
|
||||
* generator/GenBase.cs: new method AppendCustom, moved from ObjectGen.
|
||||
* generator/BoxedGen.cs, ObjectGen.cs, StructGen.cs:
|
||||
Call AppendCustom in Generate ();
|
||||
* generator/Method.cs, Parameters.cs: Add support for "out"
|
||||
parameters. Additionally, output an accessor instead of a
|
||||
regular method if it is an accessor-style function (ie GetStartIter).
|
||||
* generator/Property.cs: Add additional cast to Boxed, if necessary.
|
||||
* glue/textiter.c: New constructor for GtkTextIter.
|
||||
* glue/Makefile.am: Add textiter.c, build with Gtk+ cflags.
|
||||
* configure.in: Check for Gtk+ cflags.
|
||||
* parser/Metadata.pm, Gtk.metadata: Added.
|
||||
* parser/gapi2xml.pl: Call Metadata::fixup on the document.
|
||||
Also work around gtk's screwy boxed type name registration
|
||||
(GtkFoo -> GtkTypeFoo).
|
||||
* gtk/TextIter.custom: Added.
|
||||
|
||||
2002-06-06 Mike Kestner <mkestner@speakeasy.net>
|
||||
|
||||
* glib/Timeout.cs : new Timeout class with Add() and
|
||||
|
|
20
configure.in
20
configure.in
|
@ -39,10 +39,10 @@ fi
|
|||
|
||||
dnl for use on the build system
|
||||
dnl pkg-config is stupid
|
||||
BUILD_GLIB_CFLAGS=`$PKG_CONFIG --cflags glib-2.0`
|
||||
BUILD_GLIB_LIBS=`$PKG_CONFIG --libs glib-2.0`
|
||||
AC_SUBST(BUILD_GLIB_CFLAGS)
|
||||
AC_SUBST(BUILD_GLIB_LIBS)
|
||||
BUILD_GTK_CFLAGS=`$PKG_CONFIG --cflags gtk+-2.0`
|
||||
BUILD_GTK_LIBS=`$PKG_CONFIG --libs gtk+-2.0`
|
||||
AC_SUBST(BUILD_GTK_CFLAGS)
|
||||
AC_SUBST(BUILD_GTK_LIBS)
|
||||
|
||||
PKG_PATH=
|
||||
AC_ARG_WITH(crosspkgdir, [ --with-crosspkgdir=/path/to/pkg-config/dir],
|
||||
|
@ -58,17 +58,17 @@ AC_ARG_WITH(crosspkgdir, [ --with-crosspkgdir=/path/to/pkg-config/dir],
|
|||
)
|
||||
|
||||
## Versions of dependencies
|
||||
GLIB_REQUIRED_VERSION=2.0.0
|
||||
GTK_REQUIRED_VERSION=2.0.0
|
||||
|
||||
PKG_CHECK_MODULES(BASE_DEPENDENCIES, glib-2.0 >= $GLIB_REQUIRED_VERSION)
|
||||
PKG_CHECK_MODULES(BASE_DEPENDENCIES, gtk+-2.0 >= $GTK_REQUIRED_VERSION)
|
||||
|
||||
GLIB_CFLAGS=`$PKG_CONFIG --cflags glib-2.0`
|
||||
GLIB_LIBS=`$PKG_CONFIG --libs glib-2.0`
|
||||
GTK_CFLAGS=`$PKG_CONFIG --cflags gtk+-2.0`
|
||||
GTK_LIBS=`$PKG_CONFIG --libs gtk+-2.0`
|
||||
GMODULE_CFLAGS=`$PKG_CONFIG --cflags gmodule-2.0`
|
||||
GMODULE_LIBS=`$PKG_CONFIG --libs gmodule-2.0`
|
||||
|
||||
AC_SUBST(GLIB_CFLAGS)
|
||||
AC_SUBST(GLIB_LIBS)
|
||||
AC_SUBST(GTK_CFLAGS)
|
||||
AC_SUBST(GTK_LIBS)
|
||||
AC_SUBST(GMODULE_CFLAGS)
|
||||
AC_SUBST(GMODULE_LIBS)
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ namespace GtkSharp.Generation {
|
|||
}
|
||||
}
|
||||
|
||||
GenBase.AppendCustom(ns, Name, sw);
|
||||
sw.WriteLine ("\t}");
|
||||
sw.WriteLine ();
|
||||
sw.WriteLine ("}");
|
||||
|
|
|
@ -59,6 +59,7 @@ namespace GtkSharp.Generation {
|
|||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
String filename = dir + sep + Name + ".cs";
|
||||
Console.WriteLine ("creating " + filename);
|
||||
|
||||
FileStream stream = new FileStream (filename, FileMode.Create, FileAccess.Write);
|
||||
StreamWriter sw = new StreamWriter (stream);
|
||||
|
@ -80,6 +81,17 @@ namespace GtkSharp.Generation {
|
|||
sw.Close();
|
||||
}
|
||||
|
||||
public static void AppendCustom (string ns, string name, StreamWriter sw)
|
||||
{
|
||||
char sep = Path.DirectorySeparatorChar;
|
||||
string custom = ".." + sep + ns.ToLower() + sep + name + ".custom";
|
||||
if (File.Exists(custom)) {
|
||||
FileStream custstream = new FileStream(custom, FileMode.Open, FileAccess.Read);
|
||||
StreamReader sr = new StreamReader(custstream);
|
||||
sw.WriteLine (sr.ReadToEnd ());
|
||||
sr.Close ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ namespace GtkSharp.Generation {
|
|||
public void Generate (StreamWriter sw)
|
||||
{
|
||||
string sig, isig, call;
|
||||
|
||||
|
||||
if (parms != null) {
|
||||
sig = "(" + parms.Signature + ")";
|
||||
isig = "(IntPtr raw, " + parms.ImportSig + ");";
|
||||
|
@ -130,18 +130,37 @@ namespace GtkSharp.Generation {
|
|||
sw.WriteLine();
|
||||
|
||||
sw.Write("\t\tpublic ");
|
||||
if (elem.HasAttribute("new_flag"))
|
||||
sw.Write("new ");
|
||||
sw.WriteLine(s_ret + " " + Name + sig);
|
||||
bool is_get = (parms != null && parms.IsAccessor && Name.Substring(0, 3) == "Get");
|
||||
if (is_get) {
|
||||
s_ret = parms.AccessorReturnType;
|
||||
sw.Write(s_ret);
|
||||
sw.Write(" ");
|
||||
sw.Write(Name.Substring (3));
|
||||
sw.Write(" { get");
|
||||
} else {
|
||||
if (elem.HasAttribute("new_flag"))
|
||||
sw.Write("new ");
|
||||
sw.WriteLine(s_ret + " " + Name + sig);
|
||||
}
|
||||
sw.WriteLine("\t\t{");
|
||||
if (parms != null)
|
||||
parms.Initialize(sw, is_get);
|
||||
sw.Write("\t\t\t");
|
||||
if (m_ret == "void") {
|
||||
if (is_get || m_ret == "void") {
|
||||
sw.WriteLine(cname + call + ";");
|
||||
} else {
|
||||
sw.WriteLine("return " + SymbolTable.FromNative(rettype, cname + call) + ";");
|
||||
}
|
||||
|
||||
if (is_get)
|
||||
sw.WriteLine ("\t\t\treturn " + parms.AccessorName + ";");
|
||||
|
||||
sw.WriteLine("\t\t}");
|
||||
|
||||
sw.Write("\t\t}");
|
||||
if (is_get)
|
||||
sw.Write(" }");
|
||||
|
||||
sw.WriteLine();
|
||||
sw.WriteLine();
|
||||
|
||||
Statistics.MethodCount++;
|
||||
|
|
|
@ -96,15 +96,7 @@ namespace GtkSharp.Generation {
|
|||
GenProperties (sw);
|
||||
GenSignals (sw);
|
||||
GenMethods (sw);
|
||||
|
||||
char sep = Path.DirectorySeparatorChar;
|
||||
string custom = ".." + sep + Namespace.ToLower() + sep + Name + ".custom";
|
||||
if (File.Exists(custom)) {
|
||||
FileStream custstream = new FileStream (custom, FileMode.Open, FileAccess.Read);
|
||||
StreamReader sr = new StreamReader (custstream);
|
||||
sw.WriteLine (sr.ReadToEnd ());
|
||||
sr.Close ();
|
||||
}
|
||||
AppendCustom(Namespace, Name, sw);
|
||||
|
||||
sw.WriteLine ("\t}");
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
namespace GtkSharp.Generation {
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
public class Parameters {
|
||||
|
@ -83,6 +84,10 @@ namespace GtkSharp.Generation {
|
|||
need_sep = true;
|
||||
}
|
||||
|
||||
if (p_elem.HasAttribute("pass_as")) {
|
||||
signature += p_elem.GetAttribute("pass_as") + " ";
|
||||
}
|
||||
|
||||
signature += (cs_type + " " + name);
|
||||
signature_types += cs_type;
|
||||
call_string += call_parm;
|
||||
|
@ -91,7 +96,74 @@ namespace GtkSharp.Generation {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void Initialize (StreamWriter sw, bool is_get)
|
||||
{
|
||||
foreach (XmlNode parm in elem.ChildNodes) {
|
||||
if (parm.Name != "parameter") {
|
||||
continue;
|
||||
}
|
||||
|
||||
XmlElement p_elem = (XmlElement) parm;
|
||||
|
||||
string type = SymbolTable.GetCSType(p_elem.GetAttribute ("type"));
|
||||
string name = MangleName(p_elem.GetAttribute("name"));
|
||||
if (is_get) {
|
||||
sw.WriteLine ("\t\t\t" + type + " " + name + ";");
|
||||
}
|
||||
|
||||
if (is_get || (p_elem.HasAttribute("pass_as") && p_elem.GetAttribute ("pass_as") == "out")) {
|
||||
sw.WriteLine("\t\t\t" + name + " = new " + type + "();");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public bool IsAccessor {
|
||||
get {
|
||||
int length = 0;
|
||||
string pass_as;
|
||||
foreach (XmlNode parm in elem.ChildNodes) {
|
||||
if (parm.Name != "parameter") {
|
||||
continue;
|
||||
}
|
||||
|
||||
XmlElement p_elem = (XmlElement) parm;
|
||||
length++;
|
||||
if (length > 1)
|
||||
return false;
|
||||
if (p_elem.HasAttribute("pass_as"))
|
||||
pass_as = p_elem.GetAttribute("pass_as");
|
||||
}
|
||||
|
||||
return (length == 1 && pass_as == "out");
|
||||
}
|
||||
}
|
||||
|
||||
public string AccessorReturnType {
|
||||
get {
|
||||
foreach (XmlNode parm in elem.ChildNodes) {
|
||||
if (parm.Name != "parameter")
|
||||
continue;
|
||||
XmlElement p_elem = (XmlElement) parm;
|
||||
return SymbolTable.GetCSType(p_elem.GetAttribute ("type"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public string AccessorName {
|
||||
get {
|
||||
foreach (XmlNode parm in elem.ChildNodes) {
|
||||
if (parm.Name != "parameter")
|
||||
continue;
|
||||
XmlElement p_elem = (XmlElement) parm;
|
||||
return MangleName (p_elem.GetAttribute("name"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private string MangleName(string name)
|
||||
{
|
||||
switch (name) {
|
||||
|
|
|
@ -63,6 +63,8 @@ namespace GtkSharp.Generation {
|
|||
return;
|
||||
} else if (SymbolTable.IsObject(c_type)) {
|
||||
v_type = "GLib.Object";
|
||||
} else if (SymbolTable.IsBoxed (c_type)) {
|
||||
v_type = "GLib.Boxed";
|
||||
}
|
||||
|
||||
if (elem.HasAttribute("construct-only") && !elem.HasAttribute("readable")) {
|
||||
|
|
|
@ -87,6 +87,8 @@ namespace GtkSharp.Generation {
|
|||
}
|
||||
}
|
||||
|
||||
GenBase.AppendCustom(ns, Name, sw);
|
||||
|
||||
sw.WriteLine ("\t}");
|
||||
sw.WriteLine ();
|
||||
sw.WriteLine ("}");
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,9 +1,10 @@
|
|||
lib_LTLIBRARIES = libgtksharpglue.la
|
||||
|
||||
INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)
|
||||
INCLUDES = $(GTK_CFLAGS) -I$(top_srcdir)
|
||||
|
||||
libgtksharpglue_la_SOURCES = \
|
||||
value.c \
|
||||
textiter.c \
|
||||
#
|
||||
|
||||
libgtksharpglue.dll: $(libgtksharpglue_la_OBJECTS) libgtksharpglue.rc libgtksharpglue.def
|
||||
|
|
17
glue/textiter.c
Normal file
17
glue/textiter.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* textiter.c : Glue to allocate GtkTextIters on the heap.
|
||||
*
|
||||
* Author: Rachel Hestilow <hestilow@ximian.com>
|
||||
*
|
||||
* <c> 2002 Rachel Hestilow, Mike Kestner
|
||||
*/
|
||||
|
||||
#include <gtk/gtktextiter.h>
|
||||
|
||||
GtkTextIter*
|
||||
gtksharp_text_iter_create (void)
|
||||
{
|
||||
GtkTextIter *iter = g_new0 (GtkTextIter, 1);
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
30
gtk/TextIter.custom
Executable file
30
gtk/TextIter.custom
Executable file
|
@ -0,0 +1,30 @@
|
|||
// Gtk.TextIter.custom - Gtk TextIter class customizations
|
||||
//
|
||||
// Author: Rachel Hestilow <hestilow@ximian.com>
|
||||
//
|
||||
// (c) 2001 Mike Kestner, 2002 Rachel Hestilow
|
||||
//
|
||||
// This code is inserted after the automatically generated code.
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// TextIter Constructor
|
||||
/// </summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// Constructs a new TextIter.
|
||||
|
||||
[DllImport("gtksharpglue")]
|
||||
static extern IntPtr gtksharp_text_iter_create();
|
||||
public TextIter () : this (gtksharp_text_iter_create ())
|
||||
{
|
||||
}
|
||||
|
||||
[DllImport("glib-2.0")]
|
||||
static extern void g_free (IntPtr mem);
|
||||
|
||||
~TextIter ()
|
||||
{
|
||||
g_free (Handle);
|
||||
}
|
||||
|
190
parser/GAPI/Metadata.pm
Normal file
190
parser/GAPI/Metadata.pm
Normal file
|
@ -0,0 +1,190 @@
|
|||
#
|
||||
# Metadata.pm: Adds additional properties to a GApi tree.
|
||||
#
|
||||
# Author: Rachel Hestilow <hestilow@ximian.com>
|
||||
#
|
||||
# <c> 2002 Rachel Hestilow
|
||||
##############################################################
|
||||
|
||||
package Metadata;
|
||||
|
||||
use XML::LibXML;
|
||||
|
||||
sub new {
|
||||
my $namespace = $_[1];
|
||||
my $file = "$namespace.metadata";
|
||||
my $self = {};
|
||||
@{$self->{rules}} = ();
|
||||
$self->{metadata} = $namespace;
|
||||
bless $self;
|
||||
$self->load ($file);
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub parseClass {
|
||||
my ($node, $classes) = @_;
|
||||
my %methods = ();
|
||||
my @attrs = $node->attributes;
|
||||
my $class_name = $attrs[0]->value;
|
||||
${$classes}{$class_name} = \%methods;
|
||||
|
||||
for ($method_node = $node->firstChild; $method_node != undef; $method_node = $method_node->nextSibling ()) {
|
||||
next if $method_node->nodeName ne "method";
|
||||
$methods{$method_node->firstChild->nodeValue} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub parseData {
|
||||
my $node = $_[0];
|
||||
my @data = ();
|
||||
for ($data_node = $node->firstChild; $data_node != undef; $data_node = $data_node->nextSibling ()) {
|
||||
next if $data_node->nodeName ne "attribute";
|
||||
my @attrs = $data_node->attributes;
|
||||
my $target = $attrs[0]->value;
|
||||
my ($filter_level, $filter_value, $attr_name, $attr_value);
|
||||
for ($attr_node = $data_node->firstChild; $attr_node != undef; $attr_node = $attr_node->nextSibling ()) {
|
||||
if ($attr_node->nodeName eq "filter") {
|
||||
my @filter_attrs = $attr_node->attributes;
|
||||
$filter_level = $filter_attrs[0]->value;
|
||||
$filter_value = $attr_node->firstChild->nodeValue;
|
||||
} elsif ($attr_node->nodeName eq "name") {
|
||||
$attr_name = $attr_node->firstChild->nodeValue;
|
||||
} elsif ($attr_node->nodeName eq "value") {
|
||||
$attr_value = $attr_node->firstChild->nodeValue;
|
||||
}
|
||||
}
|
||||
my @data_attr = ("attribute", $target, "filter", $filter_level, $filter_value, $attr_name, $attr_value);
|
||||
push @data, \@data_attr;
|
||||
}
|
||||
|
||||
return @data;
|
||||
}
|
||||
|
||||
sub load {
|
||||
my ($self, $file) = @_;
|
||||
my $parser = new XML::LibXML;
|
||||
my $doc = $parser->parse_file($file);
|
||||
my $root = $doc->documentElement;
|
||||
for ($rule_node = $root->firstChild; $rule_node != undef; $rule_node = $rule_node->nextSibling ()) {
|
||||
next if $rule_node->nodeName ne "rule";
|
||||
my %classes = ();
|
||||
my @data;
|
||||
for ($node = $rule_node->firstChild; $node != undef; $node = $node->nextSibling ()) {
|
||||
if ($node->nodeName eq "class") {
|
||||
parseClass ($node, \%classes);
|
||||
} elsif ($node->nodeName eq "data") {
|
||||
@data = parseData ($node);
|
||||
}
|
||||
}
|
||||
|
||||
push @{$self->{rules}}, [\%classes, \@data];
|
||||
}
|
||||
}
|
||||
|
||||
sub fixupParams {
|
||||
my ($method_node, $data_list_ref) = @_;
|
||||
my ($params_node, $node);
|
||||
for ($node = $method_node->firstChild; $node; $node = $node->nextSibling ()) {
|
||||
if ($node->nodeName eq "parameters") {
|
||||
$params_node = $node;
|
||||
last;
|
||||
}
|
||||
}
|
||||
return if not $params_node;
|
||||
for ($node = $params_node->firstChild; $node; $node = $node->nextSibling ()) {
|
||||
my $param_type;
|
||||
foreach $attr ($node->attributes) {
|
||||
if ($attr->name eq "type") {
|
||||
$param_type = $attr->value;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
foreach $data (@$data_list_ref) {
|
||||
if ($param_type eq $$data[4]) {
|
||||
$node->setAttribute ($$data[5], $$data[6]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub fixupNamespace {
|
||||
my ($self, $ns_node) = @_;
|
||||
my $node;
|
||||
foreach $rule (@{$self->{rules}}) {
|
||||
my ($classes_ref, $data_list_ref) = @$rule;
|
||||
for ($node = $ns_node->firstChild; $node; $node = $node->nextSibling ()) {
|
||||
next if $node->nodeName ne "object";
|
||||
my $class, $methods_ref, $attr;
|
||||
foreach $attr ($node->attributes) {
|
||||
if ($attr->name eq "cname") {
|
||||
$class = $attr->value;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
my %classes = %$classes_ref;
|
||||
$methods_ref = $classes{$class};
|
||||
next if not $methods_ref;
|
||||
|
||||
for ($method_node = $node->firstChild; $method_node; $method_node = $method_node->nextSibling ()) {
|
||||
next if $method_node->nodeName ne "method";
|
||||
my $method;
|
||||
foreach $attr ($method_node->attributes) {
|
||||
if ($attr->name eq "name") {
|
||||
$method = $attr->value;
|
||||
last;
|
||||
}
|
||||
}
|
||||
next if not ${$methods_ref}{$method};
|
||||
fixupParams ($method_node, $data_list_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub fixup {
|
||||
my $doc = $_[0];
|
||||
my ($api_node, $ns_node);
|
||||
my $metadata = undef;
|
||||
|
||||
$api_node = $doc->documentElement;
|
||||
return if not ($api_node and $api_node->nodeName eq "api");
|
||||
for ($ns_node = $api_node->firstChild; $ns_node; $ns_node = $ns_node->nextSibling ()) {
|
||||
next if $ns_node->nodeName ne "namespace";
|
||||
next if not ($ns_node->attributes and (scalar (@{$ns_node->attributes})) + 1);
|
||||
my @attrs = $ns_node->attributes;
|
||||
my $namespace = $attrs[0]->value;
|
||||
if (-f "$namespace.metadata") {
|
||||
if (not ($metadata and $metadata->{namespace} eq $namespace)) {
|
||||
$metadata = new Metadata ($namespace);
|
||||
}
|
||||
$metadata->fixupNamespace ($ns_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub output {
|
||||
my $self = $_[0];
|
||||
$rule_num = 0;
|
||||
foreach $rule (@{$self->{rules}}) {
|
||||
print "Rule #$rule_num:\n";
|
||||
my ($classes_ref, $data_list_ref) = @$rule;
|
||||
my %classes = %$classes_ref;
|
||||
my @data_list = @$data_list_ref;
|
||||
foreach $class (keys (%classes)) {
|
||||
print "\tClass $class:\n";
|
||||
foreach $method (keys %{$classes{$class}}) {
|
||||
print "\t\tMethod $method\n";
|
||||
}
|
||||
}
|
||||
print "\tData:\n";
|
||||
foreach $data (@data_list) {
|
||||
printf "\t\tAdd an %s to all %s of %s %s: %s=%s\n",
|
||||
$$data[0], $$data[1], $$data[3], $$data[4], $$data[5], $$data[6];
|
||||
}
|
||||
$rule_num++;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
31
parser/Gtk.metadata
Normal file
31
parser/Gtk.metadata
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0"?>
|
||||
<metadata>
|
||||
<rule>
|
||||
<class name="GtkTextBuffer">
|
||||
<method>GetIterAtLineOffset</method>
|
||||
<method>GetIterAtLineIndex</method>
|
||||
<method>GetIterAtOffset</method>
|
||||
<method>GetIterAtLine</method>
|
||||
<method>GetStartIter</method>
|
||||
<method>GetEndIter</method>
|
||||
<method>GetBounds</method>
|
||||
<method>GetIterAtMark</method>
|
||||
<method>GetIterAtChildAnchor</method>
|
||||
<method>GetSelectionBounds</method>
|
||||
</class>
|
||||
<class name="GtkTextLayout">
|
||||
<method>GetIterAtLine</method>
|
||||
</class>
|
||||
<class name="GtkTextView">
|
||||
<method>GetIterAtLocation</method>
|
||||
<method>GetLineAtY</method>
|
||||
</class>
|
||||
<data>
|
||||
<attribute target="param">
|
||||
<filter level="type">GtkTextIter*</filter>
|
||||
<name>pass_as</name>
|
||||
<value>out</value>
|
||||
</attribute>
|
||||
</data>
|
||||
</rule>
|
||||
</metadata>
|
190
parser/Metadata.pm
Normal file
190
parser/Metadata.pm
Normal file
|
@ -0,0 +1,190 @@
|
|||
#
|
||||
# Metadata.pm: Adds additional properties to a GApi tree.
|
||||
#
|
||||
# Author: Rachel Hestilow <hestilow@ximian.com>
|
||||
#
|
||||
# <c> 2002 Rachel Hestilow
|
||||
##############################################################
|
||||
|
||||
package Metadata;
|
||||
|
||||
use XML::LibXML;
|
||||
|
||||
sub new {
|
||||
my $namespace = $_[1];
|
||||
my $file = "$namespace.metadata";
|
||||
my $self = {};
|
||||
@{$self->{rules}} = ();
|
||||
$self->{metadata} = $namespace;
|
||||
bless $self;
|
||||
$self->load ($file);
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub parseClass {
|
||||
my ($node, $classes) = @_;
|
||||
my %methods = ();
|
||||
my @attrs = $node->attributes;
|
||||
my $class_name = $attrs[0]->value;
|
||||
${$classes}{$class_name} = \%methods;
|
||||
|
||||
for ($method_node = $node->firstChild; $method_node != undef; $method_node = $method_node->nextSibling ()) {
|
||||
next if $method_node->nodeName ne "method";
|
||||
$methods{$method_node->firstChild->nodeValue} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub parseData {
|
||||
my $node = $_[0];
|
||||
my @data = ();
|
||||
for ($data_node = $node->firstChild; $data_node != undef; $data_node = $data_node->nextSibling ()) {
|
||||
next if $data_node->nodeName ne "attribute";
|
||||
my @attrs = $data_node->attributes;
|
||||
my $target = $attrs[0]->value;
|
||||
my ($filter_level, $filter_value, $attr_name, $attr_value);
|
||||
for ($attr_node = $data_node->firstChild; $attr_node != undef; $attr_node = $attr_node->nextSibling ()) {
|
||||
if ($attr_node->nodeName eq "filter") {
|
||||
my @filter_attrs = $attr_node->attributes;
|
||||
$filter_level = $filter_attrs[0]->value;
|
||||
$filter_value = $attr_node->firstChild->nodeValue;
|
||||
} elsif ($attr_node->nodeName eq "name") {
|
||||
$attr_name = $attr_node->firstChild->nodeValue;
|
||||
} elsif ($attr_node->nodeName eq "value") {
|
||||
$attr_value = $attr_node->firstChild->nodeValue;
|
||||
}
|
||||
}
|
||||
my @data_attr = ("attribute", $target, "filter", $filter_level, $filter_value, $attr_name, $attr_value);
|
||||
push @data, \@data_attr;
|
||||
}
|
||||
|
||||
return @data;
|
||||
}
|
||||
|
||||
sub load {
|
||||
my ($self, $file) = @_;
|
||||
my $parser = new XML::LibXML;
|
||||
my $doc = $parser->parse_file($file);
|
||||
my $root = $doc->documentElement;
|
||||
for ($rule_node = $root->firstChild; $rule_node != undef; $rule_node = $rule_node->nextSibling ()) {
|
||||
next if $rule_node->nodeName ne "rule";
|
||||
my %classes = ();
|
||||
my @data;
|
||||
for ($node = $rule_node->firstChild; $node != undef; $node = $node->nextSibling ()) {
|
||||
if ($node->nodeName eq "class") {
|
||||
parseClass ($node, \%classes);
|
||||
} elsif ($node->nodeName eq "data") {
|
||||
@data = parseData ($node);
|
||||
}
|
||||
}
|
||||
|
||||
push @{$self->{rules}}, [\%classes, \@data];
|
||||
}
|
||||
}
|
||||
|
||||
sub fixupParams {
|
||||
my ($method_node, $data_list_ref) = @_;
|
||||
my ($params_node, $node);
|
||||
for ($node = $method_node->firstChild; $node; $node = $node->nextSibling ()) {
|
||||
if ($node->nodeName eq "parameters") {
|
||||
$params_node = $node;
|
||||
last;
|
||||
}
|
||||
}
|
||||
return if not $params_node;
|
||||
for ($node = $params_node->firstChild; $node; $node = $node->nextSibling ()) {
|
||||
my $param_type;
|
||||
foreach $attr ($node->attributes) {
|
||||
if ($attr->name eq "type") {
|
||||
$param_type = $attr->value;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
foreach $data (@$data_list_ref) {
|
||||
if ($param_type eq $$data[4]) {
|
||||
$node->setAttribute ($$data[5], $$data[6]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub fixupNamespace {
|
||||
my ($self, $ns_node) = @_;
|
||||
my $node;
|
||||
foreach $rule (@{$self->{rules}}) {
|
||||
my ($classes_ref, $data_list_ref) = @$rule;
|
||||
for ($node = $ns_node->firstChild; $node; $node = $node->nextSibling ()) {
|
||||
next if $node->nodeName ne "object";
|
||||
my $class, $methods_ref, $attr;
|
||||
foreach $attr ($node->attributes) {
|
||||
if ($attr->name eq "cname") {
|
||||
$class = $attr->value;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
my %classes = %$classes_ref;
|
||||
$methods_ref = $classes{$class};
|
||||
next if not $methods_ref;
|
||||
|
||||
for ($method_node = $node->firstChild; $method_node; $method_node = $method_node->nextSibling ()) {
|
||||
next if $method_node->nodeName ne "method";
|
||||
my $method;
|
||||
foreach $attr ($method_node->attributes) {
|
||||
if ($attr->name eq "name") {
|
||||
$method = $attr->value;
|
||||
last;
|
||||
}
|
||||
}
|
||||
next if not ${$methods_ref}{$method};
|
||||
fixupParams ($method_node, $data_list_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub fixup {
|
||||
my $doc = $_[0];
|
||||
my ($api_node, $ns_node);
|
||||
my $metadata = undef;
|
||||
|
||||
$api_node = $doc->documentElement;
|
||||
return if not ($api_node and $api_node->nodeName eq "api");
|
||||
for ($ns_node = $api_node->firstChild; $ns_node; $ns_node = $ns_node->nextSibling ()) {
|
||||
next if $ns_node->nodeName ne "namespace";
|
||||
next if not ($ns_node->attributes and (scalar (@{$ns_node->attributes})) + 1);
|
||||
my @attrs = $ns_node->attributes;
|
||||
my $namespace = $attrs[0]->value;
|
||||
if (-f "$namespace.metadata") {
|
||||
if (not ($metadata and $metadata->{namespace} eq $namespace)) {
|
||||
$metadata = new Metadata ($namespace);
|
||||
}
|
||||
$metadata->fixupNamespace ($ns_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub output {
|
||||
my $self = $_[0];
|
||||
$rule_num = 0;
|
||||
foreach $rule (@{$self->{rules}}) {
|
||||
print "Rule #$rule_num:\n";
|
||||
my ($classes_ref, $data_list_ref) = @$rule;
|
||||
my %classes = %$classes_ref;
|
||||
my @data_list = @$data_list_ref;
|
||||
foreach $class (keys (%classes)) {
|
||||
print "\tClass $class:\n";
|
||||
foreach $method (keys %{$classes{$class}}) {
|
||||
print "\t\tMethod $method\n";
|
||||
}
|
||||
}
|
||||
print "\tData:\n";
|
||||
foreach $data (@data_list) {
|
||||
printf "\t\tAdd an %s to all %s of %s %s: %s=%s\n",
|
||||
$$data[0], $$data[1], $$data[3], $$data[4], $$data[5], $$data[6];
|
||||
}
|
||||
$rule_num++;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
16
parser/build.pl
Executable file
16
parser/build.pl
Executable file
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
$file = "../generator/gtkapi.xml";
|
||||
|
||||
unlink ($file);
|
||||
|
||||
%ns = ( "Atk" => "atk-1.0.2/atk",
|
||||
"Pango" => "pango-1.0.2/pango",
|
||||
"Gdk" => "gtk+-2.0.3/gdk",
|
||||
"Gtk" => "gtk+-2.0.3/gtk");
|
||||
|
||||
foreach $key (keys %ns) {
|
||||
$dir = $ns{$key};
|
||||
system ("./gapi_pp.pl $dir | ./gapi2xml.pl $key $file");
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
$debug=1;
|
||||
|
||||
use XML::LibXML;
|
||||
use Metadata;
|
||||
|
||||
if (!$ARGV[0]) {
|
||||
die "Usage: gapi_pp.pl <srcdir> | gapi2xml.pl <namespace> <outfile>\n";
|
||||
|
@ -96,7 +97,9 @@ while ($line = <STDIN>) {
|
|||
}
|
||||
$boxdef =~ s/\n\s*//g;
|
||||
$boxdef =~ /\(\"(\w+)\"/;
|
||||
$boxdefs{$1} = $boxdef;
|
||||
my $boxtype = $1;
|
||||
$boxtype =~ s/($ns)Type(\w+)/$ns$2/;
|
||||
$boxdefs{$boxtype} = $boxdef;
|
||||
} elsif ($line =~ /^(const|G_CONST_RETURN)?\s*\w+\s*\**\s*(\w+)\s*\(/) {
|
||||
$fname = $2;
|
||||
$fdef = "";
|
||||
|
@ -298,6 +301,10 @@ foreach $key (sort (keys (%types))) {
|
|||
addFieldElems($struct_el, split(/;/, $1));
|
||||
addFuncElems($struct_el, $key);
|
||||
}
|
||||
##############################################################
|
||||
# Add metadata
|
||||
##############################################################
|
||||
Metadata::fixup $doc;
|
||||
|
||||
##############################################################
|
||||
# Output the tree
|
||||
|
|
31
sources/Gtk.metadata
Normal file
31
sources/Gtk.metadata
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0"?>
|
||||
<metadata>
|
||||
<rule>
|
||||
<class name="GtkTextBuffer">
|
||||
<method>GetIterAtLineOffset</method>
|
||||
<method>GetIterAtLineIndex</method>
|
||||
<method>GetIterAtOffset</method>
|
||||
<method>GetIterAtLine</method>
|
||||
<method>GetStartIter</method>
|
||||
<method>GetEndIter</method>
|
||||
<method>GetBounds</method>
|
||||
<method>GetIterAtMark</method>
|
||||
<method>GetIterAtChildAnchor</method>
|
||||
<method>GetSelectionBounds</method>
|
||||
</class>
|
||||
<class name="GtkTextLayout">
|
||||
<method>GetIterAtLine</method>
|
||||
</class>
|
||||
<class name="GtkTextView">
|
||||
<method>GetIterAtLocation</method>
|
||||
<method>GetLineAtY</method>
|
||||
</class>
|
||||
<data>
|
||||
<attribute target="param">
|
||||
<filter level="type">GtkTextIter*</filter>
|
||||
<name>pass_as</name>
|
||||
<value>out</value>
|
||||
</attribute>
|
||||
</data>
|
||||
</rule>
|
||||
</metadata>
|
Loading…
Reference in a new issue