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:
Rachel Hestilow 2002-06-10 12:34:09 +00:00
parent 63624a886d
commit eea6465cf2
19 changed files with 660 additions and 29 deletions

View File

@ -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

View File

@ -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)

View File

@ -97,6 +97,7 @@ namespace GtkSharp.Generation {
}
}
GenBase.AppendCustom(ns, Name, sw);
sw.WriteLine ("\t}");
sw.WriteLine ();
sw.WriteLine ("}");

View File

@ -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 ();
}
}
}
}

View File

@ -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++;

View File

@ -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}");

View File

@ -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) {

View File

@ -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")) {

View File

@ -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

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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");
}

View 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
View 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>