2002-01-04 02:02:28 +00:00
#!/usr/bin/perl
#
# gapi2xml.pl : Generates an XML representation of GObject based APIs.
#
# Author: Mike Kestner <mkestner@speakeasy.net>
#
2004-06-25 16:35:15 +00:00
# Copyright (c) 2001-2003 Mike Kestner
# Copyright (c) 2003-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.
2002-01-04 02:02:28 +00:00
##############################################################
2003-10-09 05:54:55 +00:00
$ debug = 0 ;
2002-01-04 02:02:28 +00:00
use XML::LibXML ;
2002-06-21 20:25:43 +00:00
if ( ! $ ARGV [ 2 ] ) {
die "Usage: gapi_pp.pl <srcdir> | gapi2xml.pl <namespace> <outfile> <libname>\n" ;
2002-01-04 02:02:28 +00:00
}
$ ns = $ ARGV [ 0 ] ;
2002-06-21 20:25:43 +00:00
$ libname = $ ARGV [ 2 ] ;
2002-06-14 Rachel Hestilow <hestilow@ximian.com>
* glib/GException.cs: Added.
* generator/Ctor.cs, Method.cs: Tag function as unsafe if it throws
an exception. Call parms.HandleException.
* generator/Paramaters.cs: Add property ThrowsException (based
on a trailing GError**). If ThrowsException, mask GError in the
signature, initialize a GError in Initialize, and add new method
HandleException to throw an exception if error != null.
* generator/SymbolTable.cs: Add gdk-pixbuf DLL, and GError type.
* gdk.imaging, gdk.imaging/Makefile.in, gdk.imaging/makefile.win32:
Added.
* configure.in, Makefile, makefile.win32: Build gdk.imaging.
* gtk/Makefile.in, gtk/makefile.win32: Link against gdk.imaging.
* parser/gapi2xml.pl: Support namespace renaming.
* parser/build.pl: Build gdk-pixbuf as gdk.imaging.
svn path=/trunk/gtk-sharp/; revision=5281
2002-06-14 18:27:04 +00:00
2002-01-04 02:02:28 +00:00
##############################################################
2002-06-21 20:25:43 +00:00
# Check if the filename provided exists. We parse existing files into
2002-01-04 02:02:28 +00:00
# a tree and append the namespace to the root node. If the file doesn't
# exist, we create a doc tree and root node to work with.
##############################################################
2002-06-21 20:25:43 +00:00
if ( - e $ ARGV [ 1 ] ) {
2002-01-04 02:02:28 +00:00
#parse existing file and get root node.
$ doc = XML::LibXML - > new - > parse_file ( $ ARGV [ 1 ] ) ;
$ root = $ doc - > getDocumentElement ( ) ;
} else {
$ doc = XML::LibXML::Document - > new ( ) ;
$ root = $ doc - > createElement ( 'api' ) ;
$ doc - > setDocumentElement ( $ root ) ;
2003-01-22 13:57:34 +00:00
$ warning_node = XML::LibXML::Comment - > new ( "\n\n This file was automatically generated.\n Please DO NOT MODIFY THIS FILE, modify .metadata files instead.\n\n" ) ;
$ root - > appendChild ( $ warning_node ) ;
2002-01-04 02:02:28 +00:00
}
$ ns_elem = $ doc - > createElement ( 'namespace' ) ;
2002-06-21 20:25:43 +00:00
$ ns_elem - > setAttribute ( 'name' , $ ns ) ;
$ ns_elem - > setAttribute ( 'library' , $ libname ) ;
2002-01-04 02:02:28 +00:00
$ root - > appendChild ( $ ns_elem ) ;
##############################################################
# First we parse the input for typedefs, structs, enums, and class_init funcs
# and put them into temporary hashes.
##############################################################
while ( $ line = <STDIN> ) {
if ( $ line =~ /typedef\s+(struct\s+\w+\s+)\*+(\w+);/ ) {
$ ptrs { $ 2 } = $ 1 ;
} elsif ( $ line =~ /typedef\s+(struct\s+\w+)\s+(\w+);/ ) {
2002-07-19 04:07:50 +00:00
next if ( $ 2 =~ /Private$/ ) ;
2002-07-30 23:02:12 +00:00
# fixme: siiigh
$ 2 = "GdkDrawable" if ( $ 1 eq "_GdkDrawable" ) ;
2002-01-04 02:02:28 +00:00
$ types { $ 2 } = $ 1 ;
2004-01-26 04:10:32 +00:00
} elsif ( $ line =~ /typedef\s+struct/ ) {
$ sdef = $ line ;
while ( $ line = <STDIN> ) {
$ sdef . = $ line ;
last if ( $ line =~ /^}/ ) ;
}
$ sdef =~ s!/\*.*?(\*/|\n)!!g ;
$ sdef =~ s/\n\s*//g ;
$ types { $ 1 } = $ sdef if ( $ sdef =~ /.*\}\s*(\w+);/ ) ;
2004-01-26 04:53:05 +00:00
} elsif ( $ line =~ /typedef\s+(unsigned\s+\w+)\s+(\**)(\w+);/ ) {
$ types { $ 3 } = $ 1 . $ 2 ;
2003-06-14 16:15:17 +00:00
} elsif ( $ line =~ /typedef\s+(\w+)\s+(\**)(\w+);/ ) {
$ types { $ 3 } = $ 1 . $ 2 ;
2003-12-12 22:36:52 +00:00
} elsif ( $ line =~ /typedef\s+enum\s+(\w+)\s+(\w+);/ ) {
$ etypes { $ 1 } = $ 2 ;
2004-10-29 20:33:07 +00:00
} elsif ( $ line =~ /^((deprecated)?typedef\s+)?\benum\b/ ) {
2002-01-04 02:02:28 +00:00
$ edef = $ line ;
while ( $ line = <STDIN> ) {
$ edef . = $ line ;
2004-10-29 20:33:07 +00:00
last if ( $ line =~ /^(deprecated)?}\s*(\w+)?;/ ) ;
2002-01-04 02:02:28 +00:00
}
$ edef =~ s/\n\s*//g ;
$ edef =~ s | /\*.*?\*/ || g ;
2003-10-02 15:48:36 +00:00
if ( $ edef =~ /typedef.*}\s*(\w+);/ ) {
$ ename = $ 1 ;
2004-10-29 20:33:07 +00:00
} elsif ( $ edef =~ /^(deprecated)?enum\s+(\w+)\s*{/ ) {
$ ename = $ 2 ;
2003-10-02 15:48:36 +00:00
} else {
print "Unexpected enum format\n$edef" ;
next ;
}
2002-01-04 02:02:28 +00:00
$ edefs { $ ename } = $ edef ;
2002-01-10 15:01:31 +00:00
} elsif ( $ line =~ /typedef\s+\w+\s*\**\s*\(\*\s*(\w+)\)\s*\(/ ) {
2002-01-04 02:02:28 +00:00
$ fname = $ 1 ;
$ fdef = "" ;
while ( $ line !~ /;/ ) {
$ fdef . = $ line ;
$ line = <STDIN> ;
}
$ fdef . = $ line ;
$ fdef =~ s/\n\s+//g ;
2002-01-10 15:01:31 +00:00
$ fpdefs { $ fname } = $ fdef ;
2004-10-29 20:33:07 +00:00
} elsif ( $ line =~ /^(private|deprecated)?struct\s+(\w+)/ ) {
2003-11-07 18:14:35 +00:00
next if ( $ line =~ /;/ ) ;
$ sname = $ 2 ;
2002-01-04 02:02:28 +00:00
$ sdef = $ line ;
while ( $ line = <STDIN> ) {
$ sdef . = $ line ;
2004-10-29 20:33:07 +00:00
last if ( $ line =~ /^(deprecated)?}/ ) ;
2002-01-04 02:02:28 +00:00
}
2002-01-10 15:01:31 +00:00
$ sdef =~ s!/\*.*?(\*/|\n)!!g ;
2002-01-04 02:02:28 +00:00
$ sdef =~ s/\n\s*//g ;
$ sdefs { $ sname } = $ sdef ;
2002-06-21 Rachel Hestilow <hestilow@ximian.com>
* generator/ClassBase.cs: New base class for classes and interfaces.
* generator/InterfaceGen.cs: Inherit from ClassBase, generate declarations.
* generator/ObjectGen.cs: Move half of this into ClassBase.
* generator/Method.cs: Turn all applicable Get/Set functions into .NET
accessors. Remove redundant == overload and move into Equals, as
it was confusing "!= null".
* generator/Parameters.cs: Alter signature creation to accept "is_set"
option, add support for variable arguments. Add properties "Count",
"IsVarArgs", "VAType".
* generator/Ctor.cs: Fixup for changes in Parameters (indenting,
signature creation).
* generator/Signal.cs: Support generating declarations.
* generator/SymbolTable: Change GetObjectGen to GetClassGen.
* glib/IWrapper.cs: Move "Handle" declaration to here, so
both classes and interfaces can benefit from it.
* glib/Object.cs: Inherit from IWrapper.cs
* parser/Metadata.pm: Support attribute changes on constructors,
methods, signals, and paramater lists.
* parser/gapi2xml.pl: Parse init funcs for interfaces. Ignore "_"
functions here.
* parser/gapi_pp.pl: Remove boxed_type_register check, as it will
be caught in the init funcs.
* parser/Atk.metadata: Added.
* parser/Gtk.metadata: Add all needed signal/method collision
renames. Rename GtkEditable.Editable accessors to IsEditable,
as .NET does not like accessors with the same name as their
declaring type. Tag TreeStore constructor as varargs.
* samples/ButtonApp.cs: s/EmitAdd/Add.
* samples/Menu.cs: s/EmitAdd/Add, s/Activate/Activated.
svn path=/trunk/gtk-sharp/; revision=5394
2002-06-21 17:15:19 +00:00
} elsif ( $ line =~ /^(\w+)_(class|base)_init\b/ ) {
2002-01-04 02:02:28 +00:00
$ class = StudlyCaps ( $ 1 ) ;
$ pedef = $ line ;
while ( $ line = <STDIN> ) {
$ pedef . = $ line ;
last if ( $ line =~ /^}/ ) ;
}
2002-06-25 23:19:36 +00:00
$ pedefs { lc ( $ class ) } = $ pedef ;
2002-06-21 Rachel Hestilow <hestilow@ximian.com>
* generator/ClassBase.cs: New base class for classes and interfaces.
* generator/InterfaceGen.cs: Inherit from ClassBase, generate declarations.
* generator/ObjectGen.cs: Move half of this into ClassBase.
* generator/Method.cs: Turn all applicable Get/Set functions into .NET
accessors. Remove redundant == overload and move into Equals, as
it was confusing "!= null".
* generator/Parameters.cs: Alter signature creation to accept "is_set"
option, add support for variable arguments. Add properties "Count",
"IsVarArgs", "VAType".
* generator/Ctor.cs: Fixup for changes in Parameters (indenting,
signature creation).
* generator/Signal.cs: Support generating declarations.
* generator/SymbolTable: Change GetObjectGen to GetClassGen.
* glib/IWrapper.cs: Move "Handle" declaration to here, so
both classes and interfaces can benefit from it.
* glib/Object.cs: Inherit from IWrapper.cs
* parser/Metadata.pm: Support attribute changes on constructors,
methods, signals, and paramater lists.
* parser/gapi2xml.pl: Parse init funcs for interfaces. Ignore "_"
functions here.
* parser/gapi_pp.pl: Remove boxed_type_register check, as it will
be caught in the init funcs.
* parser/Atk.metadata: Added.
* parser/Gtk.metadata: Add all needed signal/method collision
renames. Rename GtkEditable.Editable accessors to IsEditable,
as .NET does not like accessors with the same name as their
declaring type. Tag TreeStore constructor as varargs.
* samples/ButtonApp.cs: s/EmitAdd/Add.
* samples/Menu.cs: s/EmitAdd/Add, s/Activate/Activated.
svn path=/trunk/gtk-sharp/; revision=5394
2002-06-21 17:15:19 +00:00
} elsif ( $ line =~ /^(\w+)_get_type\b/ ) {
$ class = StudlyCaps ( $ 1 ) ;
$ pedef = $ line ;
while ( $ line = <STDIN> ) {
$ pedef . = $ line ;
if ( $ line =~ /g_boxed_type_register_static/ ) {
$ boxdef = $ line ;
while ( $ line !~ /;/ ) {
$ boxdef . = ( $ line = <STDIN> ) ;
}
$ boxdef =~ s/\n\s*//g ;
$ boxdef =~ /\(\"(\w+)\"/ ;
my $ boxtype = $ 1 ;
$ boxtype =~ s/($ns)Type(\w+)/$ns$2/ ;
$ boxdefs { $ boxtype } = $ boxdef ;
}
last if ( $ line =~ /^}/ ) ;
2002-01-17 00:26:46 +00:00
}
2002-06-25 23:19:36 +00:00
$ typefuncs { lc ( $ class ) } = $ pedef ;
2004-10-29 20:33:07 +00:00
} elsif ( $ line =~ /^(deprecated)?(const|G_CONST_RETURN)?\s*\w+\s*\**\s*(\w+)\s*\(/ ) {
$ fname = $ 3 ;
2002-01-04 02:02:28 +00:00
$ fdef = "" ;
while ( $ line !~ /;/ ) {
$ fdef . = $ line ;
$ line = <STDIN> ;
}
$ fdef . = $ line ;
2002-01-17 Mike Kestner <mkestner@speakeasy.net>
* generator/BoxedGen.cs : Removed Name, CName, and QualifiedName.
* generator/ObjectGen.cs : Removed Name, CName, and QualifiedName.
* generator/StructBase.cs : Add Name, CName, and QualifiedName. Add
GenCtor method. Stub GetCallString, GetImportSig, and GetSignature
methods.
* generator/StructGen.cs : Removed Name, CName, and QualifiedName.
* generator/SymbolTable.cs : Add GetDllName method.
* parser/gapi2xml.pl : Fix a couple <parameters> bugs.
svn path=/trunk/gtk-sharp/; revision=2030
2002-01-17 23:44:56 +00:00
$ fdef =~ s/\n\s*//g ;
2003-07-06 04:08:13 +00:00
if ( $ fdef !~ /^_/ ) {
$ fdefs { $ fname } = $ fdef ;
}
2004-01-28 21:44:25 +00:00
} elsif ( $ line =~ /CHECK_(\w*)CAST/ ) {
$ cast_macro = $ line ;
while ( $ line =~ /\\$/ ) {
$ line = <STDIN> ;
$ cast_macro . = $ line ;
}
$ cast_macro =~ s/\\\n\s*//g ;
$ cast_macro =~ s/\s+/ /g ;
if ( $ cast_macro =~ /G_TYPE_CHECK_(\w+)_CAST.*,\s*(\w+),\s*(\w+)/ ) {
if ( $ 1 eq "INSTANCE" ) {
$ objects { $ 2 } = $ 3 . $ objects { $ 2 } ;
} else {
$ objects { $ 2 } . = ":$3" ;
}
} elsif ( $ cast_macro =~ /GTK_CHECK_CAST.*,\s*(\w+),\s*(\w+)/ ) {
$ objects { $ 1 } = $ 2 . $ objects { $ 1 } ;
} elsif ( $ cast_macro =~ /GTK_CHECK_CLASS_CAST.*,\s*(\w+),\s*(\w+)/ ) {
$ objects { $ 1 } . = ":$2" ;
2002-01-04 02:02:28 +00:00
}
2002-01-07 23:30:01 +00:00
} elsif ( $ line =~ /INSTANCE_GET_INTERFACE.*,\s*(\w+),\s*(\w+)/ ) {
$ ifaces { $ 1 } = $ 2 ;
2002-01-17 00:26:46 +00:00
} elsif ( $ line =~ /^BUILTIN\s*\{\s*\"(\w+)\".*GTK_TYPE_BOXED/ ) {
$ boxdefs { $ 1 } = $ line ;
} elsif ( $ line =~ /^BUILTIN\s*\{\s*\"(\w+)\".*GTK_TYPE_(ENUM|FLAGS)/ ) {
# ignoring these for now.
2004-10-29 20:33:07 +00:00
} elsif ( $ line =~ /^(deprecated)?\#define/ ) {
2002-07-05 20:22:21 +00:00
my $ test_ns = uc ( $ ns ) ;
2004-10-29 20:33:07 +00:00
if ( $ line =~ /^deprecated\#define\s+(\w+)\s+\"(.*)\"/ ) {
$ defines { "deprecated$1" } = $ 2 ;
} elsif ( $ line =~ /\#define\s+(\w+)\s+\"(.*)\"/ ) {
2002-07-05 20:22:21 +00:00
$ defines { $ 1 } = $ 2 ;
}
2002-01-04 02:02:28 +00:00
} else {
print $ line ;
}
}
##############################################################
# Produce the enum definitions.
##############################################################
2003-02-21 05:54:32 +00:00
% enums = ( ) ;
2002-01-04 02:02:28 +00:00
foreach $ cname ( sort ( keys ( % edefs ) ) ) {
$ ecnt + + ;
2003-12-12 22:36:52 +00:00
$ def = $ edefs { $ cname } ;
$ cname = $ etypes { $ cname } if ( exists ( $ etypes { $ cname } ) ) ;
2003-02-21 05:54:32 +00:00
$ enums { lc ( $ cname ) } = $ cname ;
2002-01-04 02:02:28 +00:00
$ enum_elem = addNameElem ( $ ns_elem , 'enum' , $ cname , $ ns ) ;
2004-10-29 20:33:07 +00:00
if ( $ def =~ /^deprecated/ ) {
$ enum_elem - > setAttribute ( "deprecated" , "1" ) ;
$ def =~ s/deprecated//g ;
}
2002-01-04 02:02:28 +00:00
if ( $ def =~ /=\s*1\s*<<\s*\d+/ ) {
$ enum_elem - > setAttribute ( 'type' , "flags" ) ;
} else {
$ enum_elem - > setAttribute ( 'type' , "enum" ) ;
}
$ def =~ /\{(.*)\}/ ;
@ vals = split ( /,\s*/ , $ 1 ) ;
@ v0 = split ( /_/ , $ vals [ 0 ] ) ;
if ( @ vals > 1 ) {
$ done = 0 ;
for ( $ idx = 0 , $ regex = "" ; $ idx < @ v0 ; $ idx + + ) {
$ regex . = ( $ v0 [ $ idx ] . "_" ) ;
foreach $ val ( @ vals ) {
$ done = 1 if ( $ val !~ /$regex/ ) ;
}
last if $ done ;
}
$ common = join ( "_" , @ v0 [ 0 .. $ idx - 1 ] ) ;
} else {
$ common = join ( "_" , @ v0 [ 0 .. $# v0 - 1 ] ) ;
}
foreach $ val ( @ vals ) {
2003-11-07 18:14:35 +00:00
if ( $ val =~ /$common\_?(\w+)\s*=\s*(\-?\d+.*)/ ) {
2002-01-04 02:02:28 +00:00
$ name = $ 1 ;
if ( $ 2 =~ /1u?\s*<<\s*(\d+)/ ) {
$ enumval = "1 << $1" ;
} else {
$ enumval = $ 2 ;
}
2003-11-07 18:14:35 +00:00
} elsif ( $ val =~ /$common\_?(\w+)/ ) {
2002-01-04 02:02:28 +00:00
$ name = $ 1 ; $ enumval = "" ;
} else {
2003-11-07 18:14:35 +00:00
die "Unexpected enum value: $val for common value $common\n" ;
2002-01-04 02:02:28 +00:00
}
$ val_elem = addNameElem ( $ enum_elem , 'member' ) ;
$ val_elem - > setAttribute ( 'cname' , "$common\_$name" ) ;
$ val_elem - > setAttribute ( 'name' , StudlyCaps ( lc ( $ name ) ) ) ;
if ( $ enumval ) {
$ val_elem - > setAttribute ( 'value' , $ enumval ) ;
}
}
}
##############################################################
# Parse the callbacks.
##############################################################
foreach $ cbname ( sort ( keys ( % fpdefs ) ) ) {
2002-01-10 15:01:31 +00:00
next if ( $ cbname !~ /$ns/ ) ;
2002-01-04 02:02:28 +00:00
$ cbcnt + + ;
$ fdef = $ cb = $ fpdefs { $ cbname } ;
$ cb_elem = addNameElem ( $ ns_elem , 'callback' , $ cbname , $ ns ) ;
$ cb =~ /typedef\s+(.*)\(.*\).*\((.*)\);/ ;
$ ret = $ 1 ; $ params = $ 2 ;
addReturnElem ( $ cb_elem , $ ret ) ;
if ( $ params && ( $ params ne "void" ) ) {
addParamsElem ( $ cb_elem , split ( /,/ , $ params ) ) ;
}
}
2002-01-07 23:30:01 +00:00
##############################################################
# Parse the interfaces list.
##############################################################
foreach $ type ( sort ( keys ( % ifaces ) ) ) {
$ iface = $ ifaces { $ type } ;
( $ inst , $ dontcare ) = split ( /:/ , delete $ objects { $ type } ) ;
2002-06-25 23:19:36 +00:00
$ initfunc = $ pedefs { lc ( $ inst ) } ;
2002-01-07 23:30:01 +00:00
$ ifacetype = delete $ types { $ iface } ;
delete $ types { $ inst } ;
2002-06-21 Rachel Hestilow <hestilow@ximian.com>
* generator/ClassBase.cs: New base class for classes and interfaces.
* generator/InterfaceGen.cs: Inherit from ClassBase, generate declarations.
* generator/ObjectGen.cs: Move half of this into ClassBase.
* generator/Method.cs: Turn all applicable Get/Set functions into .NET
accessors. Remove redundant == overload and move into Equals, as
it was confusing "!= null".
* generator/Parameters.cs: Alter signature creation to accept "is_set"
option, add support for variable arguments. Add properties "Count",
"IsVarArgs", "VAType".
* generator/Ctor.cs: Fixup for changes in Parameters (indenting,
signature creation).
* generator/Signal.cs: Support generating declarations.
* generator/SymbolTable: Change GetObjectGen to GetClassGen.
* glib/IWrapper.cs: Move "Handle" declaration to here, so
both classes and interfaces can benefit from it.
* glib/Object.cs: Inherit from IWrapper.cs
* parser/Metadata.pm: Support attribute changes on constructors,
methods, signals, and paramater lists.
* parser/gapi2xml.pl: Parse init funcs for interfaces. Ignore "_"
functions here.
* parser/gapi_pp.pl: Remove boxed_type_register check, as it will
be caught in the init funcs.
* parser/Atk.metadata: Added.
* parser/Gtk.metadata: Add all needed signal/method collision
renames. Rename GtkEditable.Editable accessors to IsEditable,
as .NET does not like accessors with the same name as their
declaring type. Tag TreeStore constructor as varargs.
* samples/ButtonApp.cs: s/EmitAdd/Add.
* samples/Menu.cs: s/EmitAdd/Add, s/Activate/Activated.
svn path=/trunk/gtk-sharp/; revision=5394
2002-06-21 17:15:19 +00:00
2002-01-07 23:30:01 +00:00
$ ifacecnt + + ;
$ iface_el = addNameElem ( $ ns_elem , 'interface' , $ inst , $ ns ) ;
2002-08-09 03:56:27 +00:00
$ elem_table { lc ( $ inst ) } = $ iface_el ;
2002-06-21 Rachel Hestilow <hestilow@ximian.com>
* generator/ClassBase.cs: New base class for classes and interfaces.
* generator/InterfaceGen.cs: Inherit from ClassBase, generate declarations.
* generator/ObjectGen.cs: Move half of this into ClassBase.
* generator/Method.cs: Turn all applicable Get/Set functions into .NET
accessors. Remove redundant == overload and move into Equals, as
it was confusing "!= null".
* generator/Parameters.cs: Alter signature creation to accept "is_set"
option, add support for variable arguments. Add properties "Count",
"IsVarArgs", "VAType".
* generator/Ctor.cs: Fixup for changes in Parameters (indenting,
signature creation).
* generator/Signal.cs: Support generating declarations.
* generator/SymbolTable: Change GetObjectGen to GetClassGen.
* glib/IWrapper.cs: Move "Handle" declaration to here, so
both classes and interfaces can benefit from it.
* glib/Object.cs: Inherit from IWrapper.cs
* parser/Metadata.pm: Support attribute changes on constructors,
methods, signals, and paramater lists.
* parser/gapi2xml.pl: Parse init funcs for interfaces. Ignore "_"
functions here.
* parser/gapi_pp.pl: Remove boxed_type_register check, as it will
be caught in the init funcs.
* parser/Atk.metadata: Added.
* parser/Gtk.metadata: Add all needed signal/method collision
renames. Rename GtkEditable.Editable accessors to IsEditable,
as .NET does not like accessors with the same name as their
declaring type. Tag TreeStore constructor as varargs.
* samples/ButtonApp.cs: s/EmitAdd/Add.
* samples/Menu.cs: s/EmitAdd/Add, s/Activate/Activated.
svn path=/trunk/gtk-sharp/; revision=5394
2002-06-21 17:15:19 +00:00
$ classdef = $ sdefs { $ 1 } if ( $ ifacetype =~ /struct\s+(\w+)/ ) ;
if ( $ initfunc ) {
2004-03-08 18:08:48 +00:00
parseInitFunc ( $ iface_el , $ initfunc , 0 ) ;
2002-06-21 Rachel Hestilow <hestilow@ximian.com>
* generator/ClassBase.cs: New base class for classes and interfaces.
* generator/InterfaceGen.cs: Inherit from ClassBase, generate declarations.
* generator/ObjectGen.cs: Move half of this into ClassBase.
* generator/Method.cs: Turn all applicable Get/Set functions into .NET
accessors. Remove redundant == overload and move into Equals, as
it was confusing "!= null".
* generator/Parameters.cs: Alter signature creation to accept "is_set"
option, add support for variable arguments. Add properties "Count",
"IsVarArgs", "VAType".
* generator/Ctor.cs: Fixup for changes in Parameters (indenting,
signature creation).
* generator/Signal.cs: Support generating declarations.
* generator/SymbolTable: Change GetObjectGen to GetClassGen.
* glib/IWrapper.cs: Move "Handle" declaration to here, so
both classes and interfaces can benefit from it.
* glib/Object.cs: Inherit from IWrapper.cs
* parser/Metadata.pm: Support attribute changes on constructors,
methods, signals, and paramater lists.
* parser/gapi2xml.pl: Parse init funcs for interfaces. Ignore "_"
functions here.
* parser/gapi_pp.pl: Remove boxed_type_register check, as it will
be caught in the init funcs.
* parser/Atk.metadata: Added.
* parser/Gtk.metadata: Add all needed signal/method collision
renames. Rename GtkEditable.Editable accessors to IsEditable,
as .NET does not like accessors with the same name as their
declaring type. Tag TreeStore constructor as varargs.
* samples/ButtonApp.cs: s/EmitAdd/Add.
* samples/Menu.cs: s/EmitAdd/Add, s/Activate/Activated.
svn path=/trunk/gtk-sharp/; revision=5394
2002-06-21 17:15:19 +00:00
} else {
warn "Don't have an init func for $inst.\n" if $ debug ;
}
2002-01-07 23:30:01 +00:00
}
2002-01-04 02:02:28 +00:00
##############################################################
# Parse the classes by walking the objects list.
##############################################################
foreach $ type ( sort ( keys ( % objects ) ) ) {
( $ inst , $ class ) = split ( /:/ , $ objects { $ type } ) ;
$ class = $ inst . "Class" if ( ! $ class ) ;
2002-06-25 23:19:36 +00:00
$ initfunc = $ pedefs { lc ( $ inst ) } ;
$ typefunc = $ typefuncs { lc ( $ inst ) } ;
2002-01-04 02:02:28 +00:00
$ insttype = delete $ types { $ inst } ;
$ classtype = delete $ types { $ class } ;
$ instdef = $ classdef = "" ;
$ instdef = $ sdefs { $ 1 } if ( $ insttype =~ /struct\s+(\w+)/ ) ;
$ classdef = $ sdefs { $ 1 } if ( $ classtype =~ /struct\s+(\w+)/ ) ;
2004-10-29 20:33:07 +00:00
$ classdef =~ s/deprecated//g ;
2002-01-04 02:02:28 +00:00
$ instdef =~ s/\s+(\*+)/\1 /g ;
warn "Strange Class $inst\n" if ( ! $ instdef && $ debug ) ;
$ classcnt + + ;
$ obj_el = addNameElem ( $ ns_elem , 'object' , $ inst , $ ns ) ;
2002-07-23 22:23:40 +00:00
$ elem_table { lc ( $ inst ) } = $ obj_el ;
2004-10-29 20:33:07 +00:00
# Check if the object is deprecated
if ( $ instdef =~ /^deprecatedstruct/ ) {
$ obj_el - > setAttribute ( "deprecated" , "1" ) ;
$ instdef =~ s/deprecated//g ;
}
2002-01-04 02:02:28 +00:00
# Extract parent and fields from the struct
if ( $ instdef =~ /^struct/ ) {
$ instdef =~ /\{(.*)\}/ ;
2004-01-28 21:44:25 +00:00
$ fieldstr = $ 1 ;
$ fieldstr =~ s | /\*.*?\*/ || g ;
@ fields = split ( /;/ , $ fieldstr ) ;
2002-01-04 02:02:28 +00:00
$ fields [ 0 ] =~ /(\w+)/ ;
$ obj_el - > setAttribute ( 'parent' , "$1" ) ;
addFieldElems ( $ obj_el , @ fields [ 1 .. $# fields ] ) ;
} elsif ( $ instdef =~ /privatestruct/ ) {
# just get the parent for private structs
$ instdef =~ /\{\s*(\w+)/ ;
$ obj_el - > setAttribute ( 'parent' , "$1" ) ;
}
# Get the props from the class_init func.
if ( $ initfunc ) {
2004-03-08 18:08:48 +00:00
parseInitFunc ( $ obj_el , $ initfunc , 1 ) ;
2002-01-04 02:02:28 +00:00
} else {
warn "Don't have an init func for $inst.\n" if $ debug ;
}
2002-06-21 Rachel Hestilow <hestilow@ximian.com>
* generator/ClassBase.cs: New base class for classes and interfaces.
* generator/InterfaceGen.cs: Inherit from ClassBase, generate declarations.
* generator/ObjectGen.cs: Move half of this into ClassBase.
* generator/Method.cs: Turn all applicable Get/Set functions into .NET
accessors. Remove redundant == overload and move into Equals, as
it was confusing "!= null".
* generator/Parameters.cs: Alter signature creation to accept "is_set"
option, add support for variable arguments. Add properties "Count",
"IsVarArgs", "VAType".
* generator/Ctor.cs: Fixup for changes in Parameters (indenting,
signature creation).
* generator/Signal.cs: Support generating declarations.
* generator/SymbolTable: Change GetObjectGen to GetClassGen.
* glib/IWrapper.cs: Move "Handle" declaration to here, so
both classes and interfaces can benefit from it.
* glib/Object.cs: Inherit from IWrapper.cs
* parser/Metadata.pm: Support attribute changes on constructors,
methods, signals, and paramater lists.
* parser/gapi2xml.pl: Parse init funcs for interfaces. Ignore "_"
functions here.
* parser/gapi_pp.pl: Remove boxed_type_register check, as it will
be caught in the init funcs.
* parser/Atk.metadata: Added.
* parser/Gtk.metadata: Add all needed signal/method collision
renames. Rename GtkEditable.Editable accessors to IsEditable,
as .NET does not like accessors with the same name as their
declaring type. Tag TreeStore constructor as varargs.
* samples/ButtonApp.cs: s/EmitAdd/Add.
* samples/Menu.cs: s/EmitAdd/Add, s/Activate/Activated.
svn path=/trunk/gtk-sharp/; revision=5394
2002-06-21 17:15:19 +00:00
# Get the interfaces from the class_init func.
if ( $ typefunc ) {
parseTypeFunc ( $ obj_el , $ typefunc ) ;
} else {
warn "Don't have a GetType func for $inst.\n" if $ debug ;
}
2002-01-04 02:02:28 +00:00
}
##############################################################
# Parse the remaining types.
##############################################################
foreach $ key ( sort ( keys ( % types ) ) ) {
$ lasttype = $ type = $ key ;
while ( $ type && ( $ types { $ type } !~ /struct/ ) ) {
$ lasttype = $ type ;
$ type = $ types { $ type } ;
}
if ( $ types { $ type } =~ /struct\s+(\w+)/ ) {
$ type = $ 1 ;
2004-01-26 04:10:32 +00:00
if ( exists ( $ sdefs { $ type } ) ) {
$ def = $ sdefs { $ type } ;
} else {
$ def = "privatestruct" ;
}
} elsif ( $ types { $ type } =~ /struct/ && $ type =~ /^$ns/ ) {
$ def = $ types { $ type } ;
2002-01-04 02:02:28 +00:00
} else {
$ elem = addNameElem ( $ ns_elem , 'alias' , $ key , $ ns ) ;
$ elem - > setAttribute ( 'type' , $ lasttype ) ;
warn "alias $key to $lasttype\n" if $ debug ;
next ;
}
2002-07-30 23:02:12 +00:00
# fixme: hack
if ( $ key eq "GdkBitmap" ) {
$ struct_el = addNameElem ( $ ns_elem , 'object' , $ key , $ ns ) ;
} elsif ( exists ( $ boxdefs { $ key } ) ) {
2002-01-17 00:26:46 +00:00
$ struct_el = addNameElem ( $ ns_elem , 'boxed' , $ key , $ ns ) ;
} else {
$ struct_el = addNameElem ( $ ns_elem , 'struct' , $ key , $ ns ) ;
}
2002-07-23 22:23:40 +00:00
2004-10-29 20:33:07 +00:00
if ( $ def =~ /^deprecated/ ) {
$ struct_el - > setAttribute ( "deprecated" , "1" ) ;
$ def =~ s/deprecated//g ;
}
2002-07-23 22:23:40 +00:00
$ elem_table { lc ( $ key ) } = $ struct_el ;
2002-01-04 02:02:28 +00:00
$ def =~ s/\s+/ /g ;
2002-07-19 05:44:32 +00:00
if ( $ def =~ /privatestruct/ ) {
$ struct_el - > setAttribute ( 'opaque' , 'true' ) ;
} else {
$ def =~ /\{(.+)\}/ ;
addFieldElems ( $ struct_el , split ( /;/ , $ 1 ) ) ;
}
2002-01-04 02:02:28 +00:00
}
2002-07-06 07:08:19 +00:00
2002-09-08 01:29:07 +00:00
# really, _really_ opaque structs that aren't even defined in sources. Lovely.
foreach $ key ( sort ( keys ( % ptrs ) ) ) {
next if $ ptrs { $ key } !~ /struct\s+(\w+)/ ;
$ type = $ 1 ;
$ struct_el = addNameElem ( $ ns_elem , 'struct' , $ key , $ ns ) ;
$ struct_el - > setAttribute ( 'opaque' , 'true' ) ;
$ elem_table { lc ( $ key ) } = $ struct_el ;
}
2002-07-23 22:23:40 +00:00
addFuncElems ( ) ;
2003-07-06 04:08:13 +00:00
addStaticFuncElems ( ) ;
2002-07-23 22:23:40 +00:00
2002-07-06 07:08:19 +00:00
# This should probably be done in a more generic way
foreach $ define ( sort ( keys ( % defines ) ) ) {
next if $ define !~ /[A-Z]_STOCK_/ ;
if ( $ stocks { $ ns } ) {
$ stock_el = $ stocks { $ ns } ;
} else {
$ stock_el = addNameElem ( $ ns_elem , "object" , $ ns . "Stock" , $ ns ) ;
$ stocks { $ ns } = $ stock_el ;
}
$ string_el = addNameElem ( $ stock_el , "static-string" , $ define ) ;
$ string_name = lc ( $ define ) ;
$ string_name =~ s/\w+_stock_// ;
$ string_el - > setAttribute ( 'name' , StudlyCaps ( $ string_name ) ) ;
$ string_el - > setAttribute ( 'value' , $ defines { $ define } ) ;
}
2002-01-04 02:02:28 +00:00
##############################################################
# Output the tree
##############################################################
if ( $ ARGV [ 1 ] ) {
open ( XMLFILE , ">$ARGV[1]" ) ||
die "Couldn't open $ARGV[1] for writing.\n" ;
print XMLFILE $ doc - > toString ( ) ;
close ( XMLFILE ) ;
} else {
print $ doc - > toString ( ) ;
}
##############################################################
# Generate a few stats from the parsed source.
##############################################################
$ scnt = keys ( % sdefs ) ; $ fcnt = keys ( % fdefs ) ; $ tcnt = keys ( % types ) ;
print "structs: $scnt enums: $ecnt callbacks: $cbcnt\n" ;
print "funcs: $fcnt types: $tcnt classes: $classcnt\n" ;
2004-11-05 16:47:15 +00:00
print "props: $propcnt childprops: $childpropcnt signals: $sigcnt\n\n" ;
2002-01-04 02:02:28 +00:00
sub addFieldElems
{
my ( $ parent , @ fields ) = @ _ ;
foreach $ field ( @ fields ) {
next if ( $ field !~ /\S/ ) ;
$ field =~ s/\s+(\*+)/\1 /g ;
2004-07-30 20:36:39 +00:00
$ field =~ s/(\w+)\s+const /const \1 /g ;
2002-01-04 02:02:28 +00:00
$ field =~ s/const /const\-/g ;
2002-07-26 06:08:52 +00:00
$ field =~ s/struct /struct\-/g ;
2002-07-13 Rachel Hestilow <hestilow@ximian.com>
* parser/Gnome.metadata, Gtk.metadata: More conflict
fixes.
* parser/build.pl: Fully qualify all lib names. (Gtk+ packages
are now LFS-compliant in Debian...)
* parser/gapi2xml.pl: Fix for whitespace in fields, defines,
and docs.
* generator/BoxedGen.cs: Remove extraneous CallByName definition,
add "override" keyword to FromNative.
(Generate): Generate methods after fields.
* generator/ClassBase.cs: Change CallByName, FromNative to virtual.
(.ctor): Ignore "hidden" nodes. Set container on signal.
(GenSignals, GenMethods): Add "implementor" argument for interface
use.
(Get(Method|Signal|Property)Recursively): Rework to correctly
recurse interfaces.
(Implements): Added.
* generator/Ctor.cs (Initialize): Move clash initialization completely
out of Generate, so we can check for collisions.
* generator/Method.cs (GenerateDeclCommon): Check for duplicates,
for "new" keyword.
(Generate): Add "implementor" argument.
* generator/ObjectGen.cs (Generate): Initialize ctor clashes on
this and all parents, before generating.
(Ctors, InitializeCtors): Added.
* generator/Signal.cs: Store the container_type, check for
collisions.
* generator/StructGen.cs: Add "override" keyword to overriden methods.
* gtk/FileSelection.custom (ActionArea): Add "new" keyword.
svn path=/trunk/gtk-sharp/; revision=5782
2002-07-13 20:31:23 +00:00
$ field =~ s/.*\*\///g ;
next if ( $ field !~ /\S/ ) ;
2004-10-29 20:33:07 +00:00
2002-01-04 02:02:28 +00:00
if ( $ field =~ /(\S+\s+\*?)\(\*\s*(.+)\)\s*\((.*)\)/ ) {
$ elem = addNameElem ( $ parent , 'callback' , $ 2 ) ;
addReturnElem ( $ elem , $ 1 ) ;
addParamsElem ( $ elem , $ 3 ) ;
2004-01-26 04:53:05 +00:00
} elsif ( $ field =~ /(unsigned )?(\S+)\s+(.+)/ ) {
2004-01-28 21:44:25 +00:00
my $ type = $ 1 . $ 2 ; $ symb = $ 3 ;
2002-01-04 02:02:28 +00:00
foreach $ tok ( split ( /,\s*/ , $ symb ) ) {
if ( $ tok =~ /(\w+)\s*\[(.*)\]/ ) {
$ elem = addNameElem ( $ parent , 'field' , $ 1 ) ;
$ elem - > setAttribute ( 'array_len' , "$2" ) ;
2002-01-06 13:33:25 +00:00
} elsif ( $ tok =~ /(\w+)\s*\:\s*(\d+)/ ) {
$ elem = addNameElem ( $ parent , 'field' , $ 1 ) ;
$ elem - > setAttribute ( 'bits' , "$2" ) ;
2002-01-04 02:02:28 +00:00
} else {
2002-01-07 00:25:51 +00:00
$ elem = addNameElem ( $ parent , 'field' , $ tok ) ;
2002-01-04 02:02:28 +00:00
}
2002-01-06 13:33:25 +00:00
$ elem - > setAttribute ( 'type' , "$type" ) ;
2002-01-04 02:02:28 +00:00
}
} else {
die "$field\n" ;
}
}
}
sub addFuncElems
{
2002-07-23 22:23:40 +00:00
my ( $ obj_el , $ inst , $ prefix ) ;
2002-01-04 02:02:28 +00:00
$ fcnt = keys ( % fdefs ) ;
2002-07-23 22:23:40 +00:00
foreach $ mname ( sort ( keys ( % fdefs ) ) ) {
next if ( $ mname =~ /^_/ ) ;
$ obj_el = "" ;
$ prefix = $ mname ;
2002-08-03 22:24:37 +00:00
$ prepend = undef ;
2002-07-23 22:23:40 +00:00
while ( $ prefix =~ /(\w+)_/ ) {
$ prefix = $ key = $ 1 ;
$ key =~ s/_//g ;
2002-08-03 22:24:37 +00:00
# FIXME: lame Gdk API hack
if ( $ key eq "gdkdraw" ) {
$ key = "gdkdrawable" ;
$ prepend = "draw_" ;
}
2002-07-23 22:23:40 +00:00
if ( exists ( $ elem_table { $ key } ) ) {
$ prefix . = "_" ;
$ obj_el = $ elem_table { $ key } ;
$ inst = $ key ;
last ;
2003-07-06 04:08:13 +00:00
} elsif ( exists ( $ enums { $ key } ) && ( $ mname =~ /_get_type/ ) ) {
delete $ fdefs { $ mname } ;
last ;
2002-07-23 22:23:40 +00:00
}
}
next if ( ! $ obj_el ) ;
$ mdef = delete $ fdefs { $ mname } ;
2004-10-29 20:33:07 +00:00
2002-02-08 23:56:27 +00:00
if ( $ mname =~ /$prefix(new)/ ) {
2004-10-29 20:33:07 +00:00
$ el = addNameElem ( $ obj_el , 'constructor' , $ mname ) ;
if ( $ mdef =~ /^deprecated/ ) {
$ el - > setAttribute ( "deprecated" , "1" ) ;
$ mdef =~ s/deprecated//g ;
}
2002-02-08 23:56:27 +00:00
$ drop_1st = 0 ;
2002-07-23 22:23:40 +00:00
} else {
2002-08-03 22:24:37 +00:00
$ el = addNameElem ( $ obj_el , 'method' , $ mname , $ prefix , $ prepend ) ;
2004-10-29 20:33:07 +00:00
if ( $ mdef =~ /^deprecated/ ) {
$ el - > setAttribute ( "deprecated" , "1" ) ;
$ mdef =~ s/deprecated//g ;
}
2002-07-23 22:23:40 +00:00
$ mdef =~ /(.*?)\w+\s*\(/ ;
2002-01-04 02:02:28 +00:00
addReturnElem ( $ el , $ 1 ) ;
2002-07-23 22:23:40 +00:00
$ mdef =~ /\(\s*(const)?\s*(\w+)/ ;
if ( lc ( $ 2 ) ne $ inst ) {
$ el - > setAttribute ( "shared" , "true" ) ;
$ drop_1st = 0 ;
} else {
$ drop_1st = 1 ;
}
2002-01-04 02:02:28 +00:00
}
2003-07-06 04:08:13 +00:00
parseParms ( $ el , $ mdef , $ drop_1st ) ;
2002-02-17 20:54:54 +00:00
2003-07-06 04:08:13 +00:00
}
}
sub parseParms
{
my ( $ el , $ mdef , $ drop_1st ) = @ _ ;
if ( ( $ mdef =~ /\((.*)\)/ ) && ( $ 1 ne "void" ) ) {
@ parms = ( ) ;
$ parm = "" ;
$ pcnt = 0 ;
foreach $ char ( split ( // , $ 1 ) ) {
if ( $ char eq "(" ) {
$ pcnt + + ;
} elsif ( $ char eq ")" ) {
$ pcnt - - ;
} elsif ( ( $ pcnt == 0 ) && ( $ char eq "," ) ) {
2002-02-17 20:54:54 +00:00
@ parms = ( @ parms , $ parm ) ;
2003-07-06 04:08:13 +00:00
$ parm = "" ;
next ;
2002-02-17 20:54:54 +00:00
}
2003-07-06 04:08:13 +00:00
$ parm . = $ char ;
}
if ( $ parm ) {
@ parms = ( @ parms , $ parm ) ;
}
# @parms = split(/,/, $1);
( $ dump , @ parms ) = @ parms if $ drop_1st ;
if ( @ parms > 0 ) {
addParamsElem ( $ el , @ parms ) ;
}
}
}
sub addStaticFuncElems
{
my ( $ global_el , $ ns_prefix ) ;
@ mnames = sort ( keys ( % fdefs ) ) ;
$ mcount = @ mnames ;
return if ( $ mcount == 0 ) ;
$ ns_prefix = "" ;
$ global_el = "" ;
for ( $ i = 0 ; $ i < $ mcount ; $ i + + ) {
$ mname = $ mnames [ $ i ] ;
$ prefix = $ mname ;
next if ( $ prefix =~ /^_/ ) ;
if ( $ ns_prefix eq "" ) {
my ( @ toks ) = split ( /_/ , $ prefix ) ;
for ( $ j = 0 ; $ j < @ toks ; $ j + + ) {
if ( join ( "" , @ toks [ 0 .. $ j ] ) eq lc ( $ ns ) ) {
$ ns_prefix = join ( "_" , @ toks [ 0 .. $ j ] ) ;
last ;
}
}
next if ( $ ns_prefix eq "" ) ;
}
next if ( $ mname !~ /^$ns_prefix/ ) ;
if ( $ mname =~ /($ns_prefix)_([a-zA-Z]+)_\w+/ ) {
$ classname = $ 2 ;
2003-07-11 02:00:13 +00:00
$ key = $ prefix = $ 1 . "_" . $ 2 . "_" ;
$ key =~ s/_//g ;
2003-07-06 04:08:13 +00:00
$ cnt = 1 ;
2003-07-11 02:00:13 +00:00
if ( exists ( $ enums { $ key } ) ) {
$ cnt = 1 ;
} elsif ( $ classname ne "set" && $ classname ne "get" &&
2003-07-06 04:08:13 +00:00
$ classname ne "scan" && $ classname ne "find" &&
$ classname ne "add" && $ classname ne "remove" &&
$ classname ne "free" && $ classname ne "register" &&
$ classname ne "execute" && $ classname ne "show" &&
2003-10-19 01:35:24 +00:00
$ classname ne "parse" && $ classname ne "paint" &&
$ classname ne "string" ) {
2003-07-06 04:08:13 +00:00
while ( $ mnames [ $ i + $ cnt ] =~ /$prefix/ ) { $ cnt + + ; }
}
if ( $ cnt == 1 ) {
$ mdef = delete $ fdefs { $ mname } ;
2004-10-29 20:33:07 +00:00
2003-07-06 04:08:13 +00:00
if ( ! $ global_el ) {
2003-07-11 02:00:13 +00:00
$ global_el = $ doc - > createElement ( 'class' ) ;
2003-07-06 04:08:13 +00:00
$ global_el - > setAttribute ( 'name' , "Global" ) ;
2003-07-11 02:00:13 +00:00
$ global_el - > setAttribute ( 'cname' , $ ns . "Global" ) ;
2003-07-06 04:08:13 +00:00
$ ns_elem - > appendChild ( $ global_el ) ;
}
$ el = addNameElem ( $ global_el , 'method' , $ mname , $ ns_prefix ) ;
2004-10-29 20:33:07 +00:00
if ( $ mdef =~ /^deprecated/ ) {
$ el - > setAttribute ( "deprecated" , "1" ) ;
$ mdef =~ s/deprecated//g ;
}
2003-07-06 04:08:13 +00:00
$ mdef =~ /(.*?)\w+\s*\(/ ;
addReturnElem ( $ el , $ 1 ) ;
$ el - > setAttribute ( "shared" , "true" ) ;
parseParms ( $ el , $ mdef , 0 ) ;
next ;
} else {
2003-07-11 02:00:13 +00:00
$ class_el = $ doc - > createElement ( 'class' ) ;
2003-07-06 04:08:13 +00:00
$ class_el - > setAttribute ( 'name' , StudlyCaps ( $ classname ) ) ;
2003-07-11 02:00:13 +00:00
$ class_el - > setAttribute ( 'cname' , StudlyCaps ( $ prefix ) ) ;
2003-07-06 04:08:13 +00:00
$ ns_elem - > appendChild ( $ class_el ) ;
for ( $ j = 0 ; $ j < $ cnt ; $ j + + ) {
$ mdef = delete $ fdefs { $ mnames [ $ i + $ j ] } ;
2004-10-29 20:33:07 +00:00
2003-07-06 04:08:13 +00:00
$ el = addNameElem ( $ class_el , 'method' , $ mnames [ $ i + $ j ] , $ prefix ) ;
2004-10-29 20:33:07 +00:00
if ( $ mdef =~ /^deprecated/ ) {
$ el - > setAttribute ( "deprecated" , "1" ) ;
$ mdef =~ s/deprecated//g ;
}
2003-07-06 04:08:13 +00:00
$ mdef =~ /(.*?)\w+\s*\(/ ;
addReturnElem ( $ el , $ 1 ) ;
$ el - > setAttribute ( "shared" , "true" ) ;
parseParms ( $ el , $ mdef , 0 ) ;
}
$ i += ( $ cnt - 1 ) ;
next ;
2002-01-04 02:02:28 +00:00
}
}
}
}
sub addNameElem
{
2002-08-03 22:24:37 +00:00
my ( $ node , $ type , $ cname , $ prefix , $ prepend ) = @ _ ;
2002-01-04 02:02:28 +00:00
my $ elem = $ doc - > createElement ( $ type ) ;
$ node - > appendChild ( $ elem ) ;
if ( $ prefix ) {
2003-01-12 17:45:19 +00:00
my $ match ;
if ( $ cname =~ /$prefix(\w+)/ ) {
$ match = $ 1 ;
} else {
$ match = $ cname ;
}
2002-08-03 22:24:37 +00:00
if ( $ prepend ) {
2003-01-12 17:45:19 +00:00
$ name = $ prepend . $ match ;
2002-08-03 22:24:37 +00:00
} else {
2003-01-12 17:45:19 +00:00
$ name = $ match ;
2002-08-03 22:24:37 +00:00
}
$ elem - > setAttribute ( 'name' , StudlyCaps ( $ name ) ) ;
2002-01-04 02:02:28 +00:00
}
if ( $ cname ) {
$ elem - > setAttribute ( 'cname' , $ cname ) ;
}
return $ elem ;
}
sub addParamsElem
{
my ( $ parent , @ params ) = @ _ ;
my $ parms_elem = $ doc - > createElement ( 'parameters' ) ;
$ parent - > appendChild ( $ parms_elem ) ;
2003-10-20 20:02:16 +00:00
my $ parm_num = 0 ;
2002-01-04 02:02:28 +00:00
foreach $ parm ( @ params ) {
2003-10-20 20:02:16 +00:00
$ parm_num + + ;
2002-02-03 03:44:10 +00:00
$ parm =~ s/\s+(\*+)/\1 /g ;
2004-07-30 20:36:39 +00:00
$ parm =~ s/(\w+)\s+const /const \1 /g ;
2003-12-04 17:52:02 +00:00
$ parm =~ s/(\*+)\s*const\s+/\1 /g ;
2002-01-04 02:02:28 +00:00
$ parm =~ s/const\s+/const-/g ;
2002-02-17 20:54:54 +00:00
if ( $ parm =~ /(.*)\(\s*\**\s*(\w+)\)\s+\((.*)\)/ ) {
my $ ret = $ 1 ; my $ cbn = $ 2 ; my $ params = $ 3 ;
$ cb_elem = addNameElem ( $ parms_elem , 'callback' , $ cbn ) ;
addReturnElem ( $ cb_elem , $ ret ) ;
if ( $ params && ( $ params ne "void" ) ) {
addParamsElem ( $ cb_elem , split ( /,/ , $ params ) ) ;
}
next ;
2002-07-19 04:07:50 +00:00
} elsif ( $ parm =~ /\.\.\./ ) {
$ parm_elem = $ doc - > createElement ( 'parameter' ) ;
$ parms_elem - > appendChild ( $ parm_elem ) ;
$ parm_elem - > setAttribute ( 'ellipsis' , 'true' ) ;
next ;
2002-02-17 20:54:54 +00:00
}
$ parm_elem = $ doc - > createElement ( 'parameter' ) ;
$ parms_elem - > appendChild ( $ parm_elem ) ;
2003-10-20 20:02:16 +00:00
my $ name = "" ;
2003-11-19 18:44:01 +00:00
if ( $ parm =~ /struct\s+(\S+)\s+(\S+)/ ) {
$ parm_elem - > setAttribute ( 'type' , $ 1 ) ;
$ name = $ 2 ;
2004-01-26 04:53:05 +00:00
} elsif ( $ parm =~ /(unsigned )?(\S+)\s+(\S+)/ ) {
$ parm_elem - > setAttribute ( 'type' , $ 1 . $ 2 ) ;
$ name = $ 3 ;
2003-10-20 20:02:16 +00:00
} elsif ( $ parm =~ /(\S+)/ ) {
$ parm_elem - > setAttribute ( 'type' , $ 1 ) ;
$ name = "arg" . $ parm_num ;
}
2002-06-26 Rachel Hestilow <hestilow@ximian.com>
* configure.in, makefile, makefile.win32: add gnome.
* doc/index.html, netdoc.xsl: Add gnome.
* gdk/Event.cs: New manual wrap for GdkEvent.
* generator/ClassBase.cs: Add methods GetProperty,
GetPropertyRecursively, GetMethodRecursively.
Move Parent property here from ObjectGen.cs. Pass this pointer
into Property.
* generator/Ctor.cs: Generate docs.
* generator/Method.cs, Property.cs: Tag method as "new" if a
Method/Property with the same name is found in the class hierarchy.
* generator/SignalHandler.cs: Correctly wrap complex signal argument
types. Add gnome directory.
* generator/SymbolTable.cs: Add manually wrapped types hash
(contains GLib.GSList and Gdk.Event). Add method IsManuallyWrapped.
* glib/SList.cs: Add constructor from IntPtr.
* glue/slist.c, glue/event.c: Added (field accessor glue).
* glue/Makefile.am: Update.
* parser/Gtk.metadata: Add new signal renames for new signals
exposed by GdkEvent changes.
* parser/README, parser/build.pl: Add libgnome, libgnomecanvas,
libgnomeui.
* parser/gapi2xml.pl: Handle literal-length array parameters,
and NULL property doc strings.
* sample/: Add new test GnomeHelloWorld.cs.
* gnome/: Added.
* parser/Gnome.metadata: Added.
svn path=/trunk/gtk-sharp/; revision=5461
2002-06-26 08:36:05 +00:00
if ( $ name =~ /(\w+)\[.*\]/ ) {
2002-02-03 03:44:10 +00:00
$ name = $ 1 ;
$ parm_elem - > setAttribute ( 'array' , "true" ) ;
}
$ parm_elem - > setAttribute ( 'name' , $ name ) ;
2002-01-04 02:02:28 +00:00
}
}
sub addReturnElem
{
my ( $ parent , $ ret ) = @ _ ;
$ ret =~ s/const|G_CONST_RETURN/const-/g ;
$ ret =~ s/\s+//g ;
my $ ret_elem = $ doc - > createElement ( 'return-type' ) ;
$ parent - > appendChild ( $ ret_elem ) ;
$ ret_elem - > setAttribute ( 'type' , $ ret ) ;
return $ ret_elem ;
}
sub addPropElem
{
2004-11-05 16:47:15 +00:00
my ( $ spec , $ node , $ is_child ) = @ _ ;
2002-01-04 02:02:28 +00:00
my ( $ name , $ mode , $ docs ) ;
2002-01-12 02:08:16 +00:00
$ spec =~ /g_param_spec_(\w+)\s*\((.*)\s*\)\s*\)/ ;
2002-01-04 02:02:28 +00:00
my $ type = $ 1 ;
2002-01-12 02:08:16 +00:00
my @ params = split ( /,/ , $ 2 ) ;
2002-01-04 02:02:28 +00:00
2002-01-12 02:08:16 +00:00
$ name = $ params [ 0 ] ;
2002-07-05 20:22:21 +00:00
if ( $ defines { $ name } ) {
$ name = $ defines { $ name } ;
} else {
2002-07-13 Rachel Hestilow <hestilow@ximian.com>
* parser/Gnome.metadata, Gtk.metadata: More conflict
fixes.
* parser/build.pl: Fully qualify all lib names. (Gtk+ packages
are now LFS-compliant in Debian...)
* parser/gapi2xml.pl: Fix for whitespace in fields, defines,
and docs.
* generator/BoxedGen.cs: Remove extraneous CallByName definition,
add "override" keyword to FromNative.
(Generate): Generate methods after fields.
* generator/ClassBase.cs: Change CallByName, FromNative to virtual.
(.ctor): Ignore "hidden" nodes. Set container on signal.
(GenSignals, GenMethods): Add "implementor" argument for interface
use.
(Get(Method|Signal|Property)Recursively): Rework to correctly
recurse interfaces.
(Implements): Added.
* generator/Ctor.cs (Initialize): Move clash initialization completely
out of Generate, so we can check for collisions.
* generator/Method.cs (GenerateDeclCommon): Check for duplicates,
for "new" keyword.
(Generate): Add "implementor" argument.
* generator/ObjectGen.cs (Generate): Initialize ctor clashes on
this and all parents, before generating.
(Ctors, InitializeCtors): Added.
* generator/Signal.cs: Store the container_type, check for
collisions.
* generator/StructGen.cs: Add "override" keyword to overriden methods.
* gtk/FileSelection.custom (ActionArea): Add "new" keyword.
svn path=/trunk/gtk-sharp/; revision=5782
2002-07-13 20:31:23 +00:00
$ name =~ s/\s*\"//g ;
2002-07-05 20:22:21 +00:00
}
2004-11-05 16:47:15 +00:00
if ( $ is_child ) {
$ name = "child_$name" ;
}
2002-01-12 02:08:16 +00:00
$ mode = $ params [ $# params ] ;
if ( $ type =~ /boolean|float|double|^u?int|pointer/ ) {
2002-01-04 02:02:28 +00:00
$ type = "g$type" ;
} elsif ( $ type =~ /string/ ) {
$ type = "gchar*" ;
2003-07-05 04:07:48 +00:00
} elsif ( $ type =~ /boxed|object/ ) {
$ type = $ params [ $# params - 1 ] ;
$ type =~ s/TYPE_// ;
$ type =~ s/\s+//g ;
$ type = StudlyCaps ( lc ( $ type ) ) ;
} elsif ( $ type =~ /enum|flags/ ) {
$ type = $ params [ $# params - 2 ] ;
2002-01-04 02:02:28 +00:00
$ type =~ s/TYPE_// ;
2002-01-12 02:08:16 +00:00
$ type =~ s/\s+//g ;
2002-01-04 02:02:28 +00:00
$ type = StudlyCaps ( lc ( $ type ) ) ;
}
2004-11-05 16:47:15 +00:00
$ prop_elem = $ doc - > createElement ( $ is_child ? "childprop" : "property" ) ;
2002-01-04 02:02:28 +00:00
$ node - > appendChild ( $ prop_elem ) ;
2002-01-12 02:08:16 +00:00
$ prop_elem - > setAttribute ( 'name' , StudlyCaps ( $ name ) ) ;
$ prop_elem - > setAttribute ( 'cname' , $ name ) ;
2002-01-04 02:02:28 +00:00
$ prop_elem - > setAttribute ( 'type' , $ type ) ;
2002-01-12 02:08:16 +00:00
$ prop_elem - > setAttribute ( 'readable' , "true" ) if ( $ mode =~ /READ/ ) ;
$ prop_elem - > setAttribute ( 'writeable' , "true" ) if ( $ mode =~ /WRIT/ ) ;
$ prop_elem - > setAttribute ( 'construct-only' , "true" ) if ( $ mode =~ /CONS/ ) ;
2002-01-04 02:02:28 +00:00
}
2004-01-28 21:44:25 +00:00
sub parseTypeToken
{
my ( $ tok ) = @ _ ;
if ( $ tok =~ /G_TYPE_(\w+)/ ) {
my $ type = $ 1 ;
if ( $ type eq "NONE" ) {
return "void" ;
} elsif ( $ type eq "INT" ) {
return "gint32" ;
} elsif ( $ type eq "UINT" ) {
return "guint32" ;
} elsif ( $ type eq "ENUM" || $ type eq "FLAGS" ) {
return "gint32" ;
} elsif ( $ type eq "STRING" ) {
return "gchar*" ;
} elsif ( $ type eq "OBJECT" ) {
return "GObject*" ;
} else {
return "g" . lc ( $ type ) ;
}
} else {
$ tok =~ s/_TYPE// ;
$ tok =~ s/\|.*STATIC_SCOPE// ;
$ tok =~ s/\s+//g ;
return StudlyCaps ( lc ( $ tok ) ) ;
}
}
2002-01-04 02:02:28 +00:00
sub addSignalElem
{
my ( $ spec , $ class , $ node ) = @ _ ;
$ spec =~ s/\n\s*//g ; $ class =~ s/\n\s*//g ;
$ sig_elem = $ doc - > createElement ( 'signal' ) ;
$ node - > appendChild ( $ sig_elem ) ;
2002-02-15 01:08:57 +00:00
if ( $ spec =~ /\(\"([\w\-]+)\"/ ) {
$ sig_elem - > setAttribute ( 'name' , StudlyCaps ( $ 1 ) ) ;
$ sig_elem - > setAttribute ( 'cname' , $ 1 ) ;
}
2002-01-04 02:02:28 +00:00
$ sig_elem - > setAttribute ( 'when' , $ 1 ) if ( $ spec =~ /_RUN_(\w+)/ ) ;
my $ method = "" ;
if ( $ spec =~ /_OFFSET\s*\(\w+,\s*(\w+)\)/ ) {
$ method = $ 1 ;
} else {
@ args = split ( /,/ , $ spec ) ;
2004-01-28 21:44:25 +00:00
my $ rettype = parseTypeToken ( $ args [ 7 ] ) ;
addReturnElem ( $ sig_elem , $ rettype ) ;
$ parmcnt = $ args [ 8 ] ;
$ parmcnt =~ s/.*(\d+).*/\1/ ;
$ parms_elem = $ doc - > createElement ( 'parameters' ) ;
$ sig_elem - > appendChild ( $ parms_elem ) ;
$ parm_elem = $ doc - > createElement ( 'parameter' ) ;
$ parms_elem - > appendChild ( $ parm_elem ) ;
$ parm_elem - > setAttribute ( 'name' , "inst" ) ;
$ parm_elem - > setAttribute ( 'type' , "$inst*" ) ;
for ( my $ idx = 0 ; $ idx < $ parmcnt ; $ idx + + ) {
my $ argtype = parseTypeToken ( $ args [ 9 + $ idx ] ) ;
$ parm_elem = $ doc - > createElement ( 'parameter' ) ;
$ parms_elem - > appendChild ( $ parm_elem ) ;
$ parm_elem - > setAttribute ( 'name' , "p$idx" ) ;
$ parm_elem - > setAttribute ( 'type' , $ argtype ) ;
2002-01-04 02:02:28 +00:00
}
2004-03-18 20:25:07 +00:00
return $ class ;
2002-01-04 02:02:28 +00:00
}
2004-03-18 20:25:07 +00:00
if ( $ class =~ /;\s*(G_CONST_RETURN)?\s*(\S+\s*\**)\s*\(\*\s*$method\)\s*\((.*?)\);/ ) {
$ ret = $ 2 ; $ parms = $ 3 ;
2002-01-04 02:02:28 +00:00
addReturnElem ( $ sig_elem , $ ret ) ;
if ( $ parms && ( $ parms ne "void" ) ) {
addParamsElem ( $ sig_elem , split ( /,/ , $ parms ) ) ;
}
2004-03-18 20:25:07 +00:00
$ class =~ s/;\s*(G_CONST_RETURN)?\s*\S+\s*\**\s*\(\*\s*$method\)\s*\(.*?\);/;/ ;
2002-01-04 02:02:28 +00:00
} else {
die "$method $class" ;
}
2004-03-18 20:25:07 +00:00
return $ class ;
2004-03-08 18:08:48 +00:00
}
2002-01-04 02:02:28 +00:00
2004-03-08 18:08:48 +00:00
sub addVirtualMethods
{
my ( $ class , $ node ) = @ _ ;
$ class =~ s/\n\s*//g ;
while ( $ class =~ /;\s*(\S+\s*\**)\s*\(\*\s*(\w+)\)\s*\((.*?)\);/ ) {
$ ret = $ 1 ; $ cname = $ 2 ; $ parms = $ 3 ;
if ( $ cname !~ /reserved/ ) {
$ vm_elem = $ doc - > createElement ( 'virtual_method' ) ;
$ node - > appendChild ( $ vm_elem ) ;
$ vm_elem - > setAttribute ( 'name' , StudlyCaps ( $ cname ) ) ;
$ vm_elem - > setAttribute ( 'cname' , $ cname ) ;
addReturnElem ( $ vm_elem , $ ret ) ;
if ( $ parms && ( $ parms ne "void" ) ) {
addParamsElem ( $ vm_elem , split ( /,/ , $ parms ) ) ;
}
}
$ class =~ s/;\s*\S+\s*\**\s*\(\*\s*\w+\)\s*\(.*?\);// ;
}
2002-01-04 02:02:28 +00:00
}
2002-06-21 Rachel Hestilow <hestilow@ximian.com>
* generator/ClassBase.cs: New base class for classes and interfaces.
* generator/InterfaceGen.cs: Inherit from ClassBase, generate declarations.
* generator/ObjectGen.cs: Move half of this into ClassBase.
* generator/Method.cs: Turn all applicable Get/Set functions into .NET
accessors. Remove redundant == overload and move into Equals, as
it was confusing "!= null".
* generator/Parameters.cs: Alter signature creation to accept "is_set"
option, add support for variable arguments. Add properties "Count",
"IsVarArgs", "VAType".
* generator/Ctor.cs: Fixup for changes in Parameters (indenting,
signature creation).
* generator/Signal.cs: Support generating declarations.
* generator/SymbolTable: Change GetObjectGen to GetClassGen.
* glib/IWrapper.cs: Move "Handle" declaration to here, so
both classes and interfaces can benefit from it.
* glib/Object.cs: Inherit from IWrapper.cs
* parser/Metadata.pm: Support attribute changes on constructors,
methods, signals, and paramater lists.
* parser/gapi2xml.pl: Parse init funcs for interfaces. Ignore "_"
functions here.
* parser/gapi_pp.pl: Remove boxed_type_register check, as it will
be caught in the init funcs.
* parser/Atk.metadata: Added.
* parser/Gtk.metadata: Add all needed signal/method collision
renames. Rename GtkEditable.Editable accessors to IsEditable,
as .NET does not like accessors with the same name as their
declaring type. Tag TreeStore constructor as varargs.
* samples/ButtonApp.cs: s/EmitAdd/Add.
* samples/Menu.cs: s/EmitAdd/Add, s/Activate/Activated.
svn path=/trunk/gtk-sharp/; revision=5394
2002-06-21 17:15:19 +00:00
sub addImplementsElem
{
my ( $ spec , $ node ) = @ _ ;
$ spec =~ s/\n\s*//g ;
if ( $ spec =~ /,\s*(\w+)_TYPE_(\w+),/ ) {
$ impl_elem = $ doc - > createElement ( 'interface' ) ;
$ name = StudlyCaps ( lc ( "$1_$2" ) ) ;
$ impl_elem - > setAttribute ( "cname" , "$name" ) ;
$ node - > appendChild ( $ impl_elem ) ;
}
}
2002-01-04 02:02:28 +00:00
sub parseInitFunc
{
2004-03-08 18:08:48 +00:00
my ( $ obj_el , $ initfunc , $ is_obj ) = @ _ ;
2002-01-04 02:02:28 +00:00
my @ init_lines = split ( /\n/ , $ initfunc ) ;
my $ linenum = 0 ;
while ( $ linenum < @ init_lines ) {
my $ line = $ init_lines [ $ linenum ] ;
2002-01-12 02:08:16 +00:00
if ( $ line =~ /#define/ ) {
# FIXME: This ignores the bool helper macro thingie.
} elsif ( $ line =~ /g_object_class_install_prop/ ) {
my $ prop = $ line ;
do {
$ prop . = $ init_lines [ + + $ linenum ] ;
2003-10-07 19:28:40 +00:00
} until ( $ init_lines [ $ linenum ] =~ /\)\s*;/ ) ;
2004-11-05 16:47:15 +00:00
addPropElem ( $ prop , $ obj_el , 0 ) ;
2002-01-12 02:08:16 +00:00
$ propcnt + + ;
2004-11-05 16:47:15 +00:00
} elsif ( $ line =~ /gtk_container_class_install_child_property/ ) {
my $ prop = $ line ;
do {
$ prop . = $ init_lines [ + + $ linenum ] ;
} until ( $ init_lines [ $ linenum ] =~ /\)\s*;/ ) ;
addPropElem ( $ prop , $ obj_el , 1 ) ;
$ childpropcnt + + ;
2004-01-28 21:44:25 +00:00
} elsif ( $ line =~ /\bg.*_signal_new/ ) {
2002-01-12 02:08:16 +00:00
my $ sig = $ line ;
do {
$ sig . = $ init_lines [ + + $ linenum ] ;
} until ( $ init_lines [ $ linenum ] =~ /;/ ) ;
2004-03-18 20:25:07 +00:00
$ classdef = addSignalElem ( $ sig , $ classdef , $ obj_el ) ;
2002-01-12 02:08:16 +00:00
$ sigcnt + + ;
2002-01-04 02:02:28 +00:00
}
$ linenum + + ;
}
2004-03-08 18:08:48 +00:00
if ( $ is_obj ) {
addVirtualMethods ( $ classdef , $ obj_el ) ;
}
2002-01-04 02:02:28 +00:00
}
2002-06-21 Rachel Hestilow <hestilow@ximian.com>
* generator/ClassBase.cs: New base class for classes and interfaces.
* generator/InterfaceGen.cs: Inherit from ClassBase, generate declarations.
* generator/ObjectGen.cs: Move half of this into ClassBase.
* generator/Method.cs: Turn all applicable Get/Set functions into .NET
accessors. Remove redundant == overload and move into Equals, as
it was confusing "!= null".
* generator/Parameters.cs: Alter signature creation to accept "is_set"
option, add support for variable arguments. Add properties "Count",
"IsVarArgs", "VAType".
* generator/Ctor.cs: Fixup for changes in Parameters (indenting,
signature creation).
* generator/Signal.cs: Support generating declarations.
* generator/SymbolTable: Change GetObjectGen to GetClassGen.
* glib/IWrapper.cs: Move "Handle" declaration to here, so
both classes and interfaces can benefit from it.
* glib/Object.cs: Inherit from IWrapper.cs
* parser/Metadata.pm: Support attribute changes on constructors,
methods, signals, and paramater lists.
* parser/gapi2xml.pl: Parse init funcs for interfaces. Ignore "_"
functions here.
* parser/gapi_pp.pl: Remove boxed_type_register check, as it will
be caught in the init funcs.
* parser/Atk.metadata: Added.
* parser/Gtk.metadata: Add all needed signal/method collision
renames. Rename GtkEditable.Editable accessors to IsEditable,
as .NET does not like accessors with the same name as their
declaring type. Tag TreeStore constructor as varargs.
* samples/ButtonApp.cs: s/EmitAdd/Add.
* samples/Menu.cs: s/EmitAdd/Add, s/Activate/Activated.
svn path=/trunk/gtk-sharp/; revision=5394
2002-06-21 17:15:19 +00:00
sub parseTypeFunc
{
my ( $ obj_el , $ typefunc ) = @ _ ;
my @ type_lines = split ( /\n/ , $ typefunc ) ;
my $ linenum = 0 ;
$ impl_node = undef ;
while ( $ linenum < @ type_lines ) {
my $ line = $ type_lines [ $ linenum ] ;
if ( $ line =~ /#define/ ) {
# FIXME: This ignores the bool helper macro thingie.
} elsif ( $ line =~ /g_type_add_interface_static/ ) {
my $ prop = $ line ;
do {
$ prop . = $ type_lines [ + + $ linenum ] ;
} until ( $ type_lines [ $ linenum ] =~ /;/ ) ;
if ( not $ impl_node ) {
$ impl_node = $ doc - > createElement ( "implements" ) ;
$ obj_el - > appendChild ( $ impl_node ) ;
}
addImplementsElem ( $ prop , $ impl_node ) ;
}
$ linenum + + ;
}
}
2002-01-04 02:02:28 +00:00
##############################################################
# Converts a dash or underscore separated name to StudlyCaps.
##############################################################
% num2txt = ( '1' , "One" , '2' , "Two" , '3' , "Three" , '4' , "Four" , '5' , "Five" ,
'6' , "Six" , '7' , "Seven" , '8' , "Eight" , '9' , "Nine" , '0' , "Zero" ) ;
sub StudlyCaps
{
my ( $ symb ) = @ _ ;
$ symb =~ s/^([a-z])/\u\1/ ;
$ symb =~ s/^(\d)/\1_/ ;
$ symb =~ s/[-_]([a-z])/\u\1/g ;
$ symb =~ s/[-_](\d)/\1/g ;
$ symb =~ s/^2/Two/ ;
$ symb =~ s/^3/Three/ ;
return $ symb ;
}