summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Alburquerque <jaalburqu@svn.gnome.org>2012-09-18 15:22:25 -0400
committerJosé Alburquerque <jaalburqu@svn.gnome.org>2012-09-18 15:22:25 -0400
commit63cae37cd9dde19ffffe6d1b40c6bbb300f04a97 (patch)
tree5ba7319a65b0145780aaa1427440ebd4bbdaaf6c
parent415d91884cd3300f3cb6836f4b7fdc5364e734b3 (diff)
downloadglibmm-63cae37cd9dde19ffffe6d1b40c6bbb300f04a97.tar.gz
gmmproc: _WRAP_METHOD: Allow setting parameters from C output params.
* tools/m4/convert_base.m4 (_INITIALIZATION): Insert newlines between a possible series of statements that has been specified as an initialization. For example, the declaration, assignment and the g_free() call would each be on a seperate line in the following (from datainputstream.hg): _INITIALIZATION(`std::string&',`return-char*',`char* tmp = $4; $3 = tmp; g_free(tmp)') * tools/pm/Function.pm (FLAG_PARAM_OPTIONAL): (FLAG_PARAM_OUTPUT): Added new constant flags representing if a parameter is optional or if it is an output parameter. (EXPORT_OK): Exported the above flags so they can be used in other modules. (param_optional): Renamed to param_flags. Redesigned it to store a possible combination of both flags above and not just if a parameter is optional. (parse_param): Modified the subroutine to look for an '>>' in a possible '{.*}' following the current parameter name which would signal that the parameter is an output parameter. The syntax for signaling if a parameter is optional, is an output parameter or should be mapped to a specific C parameter would be: cpp_param_name{c_param_name>>?} c_param_name means that the C++ parameter should be mapped to the C parameter no matter the parameter order of either. The '>>' means that the parameter should be set from the C parameter because the C parameter is an output parameter. Finally, the '?' means that the parameter is optional thus overloads should be generated without that paramter. All three components within the {} are optional. A '.' may be used instead of the c parameter name if the C++ parameter name is the same as the C parameter name. (possible_args_list): Modified to use the param_flags variable. * tools/pm/Output.pm (output_wrap_vfunc_h): Modified to receive the new return type from convert_args_cpp_to_c() (see below). (output_wrap_meth): Modified to receive the new return from convert_args_cpp_to_c (see below) and pass them to the _METHOD() and _STATIC_METHOD() macros. (convert_args_cpp_to_c): Modified to generate a list of C declarations for any possible C output parameters and to generate a list of _INITIALIZE() macros to initialize the C++ parameters from the C output parameters. The function returns an array of three strings (the convert macros, the possible C declarations and the _INITIALIZE() macros in that order). * tools/pm/WrapParser.pm (string_split_commas): Modified the subroutine to ignore '>>' if they are in '{}' (so that the '>>' can signal that a parameter should be set from a C output parameter. * tools/m4/method.m4 (_METHOD, _STATIC_METHOD): Rewrote to accept C declarations of possible C output parameters and _INITIALIZE macros which would initialize the appropriate C++ parameters from the output variables and insert them appropriately in the generated code. Bug #662371.
-rw-r--r--ChangeLog62
-rw-r--r--tools/m4/convert_base.m43
-rw-r--r--tools/m4/convert_gio.m41
-rw-r--r--tools/m4/method.m4162
-rw-r--r--tools/pm/Function.pm63
-rw-r--r--tools/pm/Output.pm111
-rw-r--r--tools/pm/WrapParser.pm13
7 files changed, 293 insertions, 122 deletions
diff --git a/ChangeLog b/ChangeLog
index 37799b16..0c735b57 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,65 @@
+2012-09-18 José Alburquerque <jaalburqu@svn.gnome.org>
+
+ gmmproc: _WRAP_METHOD: Allow setting parameters from C output params.
+
+ * tools/m4/convert_base.m4 (_INITIALIZATION): Insert newlines between
+ a possible series of statements that has been specified as an
+ initialization. For example, the declaration, assignment and the
+ g_free() call would each be on a seperate line in the following (from
+ datainputstream.hg):
+
+ _INITIALIZATION(`std::string&',`return-char*',`char* tmp = $4; $3 = tmp; g_free(tmp)')
+
+ * tools/pm/Function.pm (FLAG_PARAM_OPTIONAL):
+ (FLAG_PARAM_OUTPUT): Added new constant flags representing if a
+ parameter is optional or if it is an output parameter.
+ (EXPORT_OK): Exported the above flags so they can be used in other
+ modules.
+ (param_optional): Renamed to param_flags. Redesigned it to store a
+ possible combination of both flags above and not just if a parameter
+ is optional.
+ (parse_param): Modified the subroutine to look for an '>>' in a
+ possible '{.*}' following the current parameter name which would
+ signal that the parameter is an output parameter. The syntax for
+ signaling if a parameter is optional, is an output parameter or should
+ be mapped to a specific C parameter would be:
+
+ cpp_param_name{c_param_name>>?}
+
+ c_param_name means that the C++ parameter should be mapped to the C
+ parameter no matter the parameter order of either. The '>>' means
+ that the parameter should be set from the C parameter because the C
+ parameter is an output parameter. Finally, the '?' means that the
+ parameter is optional thus overloads should be generated without that
+ paramter. All three components within the {} are optional. A '.' may
+ be used instead of the c parameter name if the C++ parameter name is
+ the same as the C parameter name.
+
+ (possible_args_list): Modified to use the param_flags variable.
+
+ * tools/pm/Output.pm (output_wrap_vfunc_h): Modified to receive the
+ new return type from convert_args_cpp_to_c() (see below).
+ (output_wrap_meth): Modified to receive the new return from
+ convert_args_cpp_to_c (see below) and pass them to the _METHOD() and
+ _STATIC_METHOD() macros.
+ (convert_args_cpp_to_c): Modified to generate a
+ list of C declarations for any possible C output parameters and to
+ generate a list of _INITIALIZE() macros to initialize the C++
+ parameters from the C output parameters. The function returns an array
+ of three strings (the convert macros, the possible C declarations and
+ the _INITIALIZE() macros in that order).
+
+ * tools/pm/WrapParser.pm (string_split_commas): Modified the
+ subroutine to ignore '>>' if they are in '{}' (so that the '>>' can
+ signal that a parameter should be set from a C output parameter.
+
+ * tools/m4/method.m4 (_METHOD, _STATIC_METHOD): Rewrote to accept
+ C declarations of possible C output parameters and _INITIALIZE macros
+ which would initialize the appropriate C++ parameters from the output
+ variables and insert them appropriately in the generated code.
+
+ Bug #662371.
+
2012-09-18 Kjell Ahlstedt <kjell.ahlstedt@bredband.net>
Improve the use of _IGNORE. Don't use gio_others.defs.
diff --git a/tools/m4/convert_base.m4 b/tools/m4/convert_base.m4
index aabbc709..ff006067 100644
--- a/tools/m4/convert_base.m4
+++ b/tools/m4/convert_base.m4
@@ -65,7 +65,8 @@ m4_m4exit(1)
# Functions for populating initialization tables.
#
define(`_INITIALIZATION',`
-m4_ifelse(`$3',,,`define(IN`'__HASH2(`$1',`$2'),`$3')')
+m4_ifelse(`$3',,,`define(IN`'__HASH2(`$1',`$2'),m4_patsubst(`$3',`; +',`;
+ '))')
')
define(`_EQUAL',`define(EV`'__HASH(`$1'),`$2')')
diff --git a/tools/m4/convert_gio.m4 b/tools/m4/convert_gio.m4
index e8a67805..4e2e4fca 100644
--- a/tools/m4/convert_gio.m4
+++ b/tools/m4/convert_gio.m4
@@ -261,6 +261,7 @@ _CONVERSION(`const Glib::VariantContainerBase&',`GVariant*',`const_cast<GVariant
#VariantType
_CONVERSION(`const GVariantType*',`Glib::VariantType',`Glib::wrap(const_cast<GVariantType*>($3), false)')
+_CONVERSION(`const Glib::VariantType&',`const GVariantType*',`$3.gobj()')
#Volume
_CONVERSION(`GVolume*',`Glib::RefPtr<Volume>',`Glib::wrap($3)')
diff --git a/tools/m4/method.m4 b/tools/m4/method.m4
index 7551c422..5dd7fd7b 100644
--- a/tools/m4/method.m4
+++ b/tools/m4/method.m4
@@ -8,96 +8,142 @@ dnl
dnl
-dnl method
-dnl $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16
-dnl _METHOD(cppname,cname,cpprettype,crettype,arglist,cargs,const,refreturn,errthrow,deprecated,constversion,ifdef,arglist_without_types,out_param,out_param_cpptype,wrap_line)
+dnl method
+dnl $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 $18
+dnl _METHOD(cppname,cname,cpprettype,crettype,arglist,cdeclarations,cargs,cinitializations,const,refreturn,errthrow,deprecated,constversion,ifdef,arglist_without_types,out_param,out_param_cpptype,wrap_line)
define(`_METHOD',`dnl
_PUSH(SECTION_CC)
-ifelse(`$10',,,`_DEPRECATE_IFDEF_START
+ifelse(`$12',,,`_DEPRECATE_IFDEF_START
')dnl
-ifelse(`$13',,,`#ifdef $13'
+ifelse(`$15',,,`#ifdef $15'
)dnl
-$3 __CPPNAME__::$1`'($5)ifelse(`$7',1,` const')
+$3 __CPPNAME__::$1`'($5)ifelse(`$9',1,` const')
{
-ifelse(`$11',,dnl
-`ifelse(`$8'`$9',,dnl If it is not errthrow or refreturn
-`ifelse(`$14',,dnl If no output parameter is specified
-`ifelse(`$3',void,dnl If it returns voids:
-` $2(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6);' dnl It it returns non-void:
-,` return _CONVERT($4,`$3',`$2`'(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6)');'dnl
-)'dnl End if it returns voids.
-dnl An output parameter is specified:
-,` _INITIALIZE($15,$4,`$14',`$2`'(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6)',$16);'dnl
-)',dnl End if an output parameter is specified.
+ifelse(`$13',,dnl
+`ifelse(`$10'`$11',,dnl If it is not errthrow or refreturn
+dnl Insert the declarations for C output parameters
+`ifelse(`$6',,,`$6
+')`'dnl
+ifelse(`$16',,dnl If no C++ output parameter is specified
+`ifelse(`$3',void,dnl If the C function returns voids:
+` $2(ifelse(`$9',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$7',,,`, ')$7);dnl
+dnl Insert the initializations for the C output parameters
+ifelse(`$8',,,`$8
+')dnl
+'dnl If the C function returns non-void:
+,dnl Insert the declarations for C output parameters
+dnl Store the return if there are C output parameters.
+`ifelse(`$6',,` return ',` `$3' retvalue = ')_CONVERT($4,`$3',`$2`'(ifelse(`$9',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$7',,,`, ')$7)');dnl
+dnl Insert the initializations for the C output parameters
+ifelse(`$8',,,`$8
+')dnl
+dnl return the value
+ifelse(`$6',,,` return retvalue;
+')dnl
+')'dnl End if it returns voids.
+dnl A C++ output parameter is specified:
+,` _INITIALIZE($17,$4,`$16',`$2`'(ifelse(`$9',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$7',,,`, ')$7)',$18);
+dnl
+dnl Insert the initializations for the C output parameters
+ifelse(`$8',,,`$8
+')dnl
+')',dnl End if a C++ output parameter is specified.
dnl If is errthrow or refreturn
-`ifelse(`$9',,,` GError* gerror = 0;')
-ifelse(`$14',,dnl If no output parameter is specified:
-` ifelse(`$3',void,,``$3' retvalue = ')_CONVERT($4,`$3',`$2`'(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6)');'dnl
-dnl An output parameter is specified:
-,` _INITIALIZE($15,$4,`$14',`$2`'(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6)',$16);'dnl
+`ifelse(`$11',,,` GError* gerror = 0;
+')dnl
+dnl Insert the declarations for C output parameters
+ifelse(`$6',,,`$6
+')`'dnl
+ifelse(`$16',,dnl If no C++ output parameter is specified:
+` ifelse(`$3',void,,``$3' retvalue = ')_CONVERT($4,`$3',`$2`'(ifelse(`$9',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$7',,,`, ')$7)');dnl
+'dnl
+,dnl A C++ output parameter is specified:
+` _INITIALIZE($17,$4,`$16',`$2`'(ifelse(`$9',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$7',,,`, ')$7)',$18);
+'dnl
)dnl
-ifelse(`$9',,,`
+ifelse(`$11',,,`
if(gerror)
::Glib::Error::throw_exception(gerror);
-')
-ifelse(`$8',,,`dnl
- if(ifelse(`$14',,`retvalue',$14))
- ifelse(`$14',,`retvalue',$14)->reference(); //The function does not do a ref for us.
')dnl
-ifelse(`$3',void,,` return retvalue;')
+ifelse(`$10',,,`
+ if(ifelse(`$16',,`retvalue',$16))
+ ifelse(`$16',,`retvalue',$16)->reference(); //The function does not do a ref for us.
+')dnl
+dnl Insert the initializations for the C output parameters
+ifelse(`$8',,,`$8
+')`'dnl
+ifelse(`$3',void,,` return retvalue;')dnl
')dnl End errthrow/refreturn
-',` return const_cast<__CPPNAME__*>(this)->$1($12);')
+',` return const_cast<__CPPNAME__*>(this)->$1($14);')
}
-ifelse(`$13',,,`
-#endif // $13
+ifelse(`$15',,,`
+#endif // $15
')dnl
-ifelse(`$10',,,`_DEPRECATE_IFDEF_END
+ifelse(`$12',,,`_DEPRECATE_IFDEF_END
')dnl
_POP()')
dnl
dnl static method
-dnl $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13
-dnl _STATIC_METHOD(cppname,cname,cpprettype,crettype,arglist,cargs,refreturn,errthrow,deprecated,ifdef,out_param,out_param_type,wrap_line)
+dnl $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
+dnl _STATIC_METHOD(cppname,cname,cpprettype,crettype,arglist,cdeclarations,cargs,cinitializations,refreturn,errthrow,deprecated,ifdef,out_param,out_param_type,wrap_line)
define(`_STATIC_METHOD',`dnl
_PUSH(SECTION_CC)
-ifelse(`$9',,,`_DEPRECATE_IFDEF_START
+ifelse(`$11',,,`_DEPRECATE_IFDEF_START
')dnl
-ifelse(`$10',,,`#ifdef $10'
+ifelse(`$12',,,`#ifdef $12'
)dnl
$3 __CPPNAME__::$1($5)
{
-ifelse(`$7'`$8',,dnl
-`ifelse(`$11',,dnl If no output parameter is specified
-`ifelse(`$3',void,,` return ')_CONVERT($4,`$3',`$2`'($6)');
-'dnl
-dnl An output parameter is specified:
-,` _INITIALIZE($12,$4,`$11',`$2`'($6)',$13);'
-)',dnl End if an output parameter is specified.
-`ifelse(`$8',,,` GError* gerror = 0;')
-ifelse(`$11',,dnl If no output parameter is specified:
- ifelse(`$3',void,,``$3' retvalue = ')_CONVERT($4,`$3',`$2`'($6)');
-dnl An output parameter is specified:
-,` _INITIALIZE($12,$4,`$11',`$2`'($6)',$13);'dnl
+ifelse(`$9'`$10',,dnl
+dnl Insert declarations for C the output parameters
+ifelse(`$6',,,`$6
+')`'dnl
+`ifelse(`$13',,
+dnl If no C++ output parameter is specified.
+` ifelse(`$3',void,,dnl
+dnl Returns non-void:
+dnl Store the return if there are C output parameters
+ifelse(`$6',,`return ',``$3' retval = '))_CONVERT($4,`$3',`$2`'($7)');'dnl
+dnl A C++ output parameter is specified so initialize it from C return
+,` _INITIALIZE($14,$4,`$13',`$2`'($7)',$15);'dnl
+)
+dnl Insert the initializations for the C output parameters if there are any
+ifelse(`$8',,,`$8
+')`'dnl
+dnl Return the value if it was stored and if the method returns something
+ifelse(`$3',void,,`ifelse(`$6',,,` return retval;
+')')dnl
+',dnl End if a C++ output parameter is specified.
+`ifelse(`$10',,,` GError* gerror = 0;')
+dnl Insert the declarations for the C output parameters
+ifelse(`$6',,,`$6
+')`'dnl
+ifelse(`$13',,dnl If no C++ output parameter is specified:
+ ifelse(`$3',void,,``$3' retvalue = ')_CONVERT($4,`$3',`$2`'($7)');dnl
+dnl A C++ output parameter is specified:
+,` _INITIALIZE($14,$4,`$13',`$2`'($7)',$15);'dnl
)dnl
-ifelse(`$8',,,`
+ifelse(`$10',,,`
if(gerror)
::Glib::Error::throw_exception(gerror);
-')
-ifelse(`$7',,,`dnl
- if(ifelse(`$11',,`retvalue',$11))
- ifelse(`$11',,`retvalue',$11)->reference(); //The function does not do a ref for us
')dnl
-ifelse(`$3',void,,` return retvalue;')
+dnl Insert the initializations for the C output parameters.
+ifelse(`$8',,,`$8
+')`'dnl
+ifelse(`$9',,,`
+ if(ifelse(`$13',,`retvalue',$13))
+ ifelse(`$13',,`retvalue',$13)->reference(); //The function does not do a ref for us
+')dnl
+ifelse(`$3',void,,` return retvalue;
+')dnl
')dnl
}
-ifelse(`$10',,,`
-#endif // $10
+ifelse(`$12',,,`
+#endif // $12
')dnl
-ifelse(`$9',,,`_DEPRECATE_IFDEF_END
+ifelse(`$11',,,`_DEPRECATE_IFDEF_END
')
_POP()')
-
-
diff --git a/tools/pm/Function.pm b/tools/pm/Function.pm
index 7073ebe0..598178b9 100644
--- a/tools/pm/Function.pm
+++ b/tools/pm/Function.pm
@@ -5,6 +5,11 @@ use warnings;
use Util;
use FunctionBase;
+# These are flags that indicate whether parameters are optional or output
+# parameters.
+use constant FLAG_PARAM_OPTIONAL => 1;
+use constant FLAG_PARAM_OUTPUT => 2;
+
BEGIN {
use Exporter ();
our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
@@ -16,7 +21,7 @@ BEGIN {
%EXPORT_TAGS = ( );
# your exported package globals go here,
# as well as any optionally exported functions
- @EXPORT_OK = qw($Var1 %Hashit &func3);
+ @EXPORT_OK = qw($Var1 %Hashit &func3 FLAG_PARAM_OPTIONAL FLAG_PARAM_OUTPUT);
}
our @EXPORT_OK;
@@ -35,7 +40,7 @@ our @EXPORT_OK;
# string array param_type;
# string array param_name;
# string array param_default_value;
-# bool array param_optional;
+# int array param_flags; (stores flags form params: 1 => optional, 2 => output)
# hash param_mappings; (maps C param names (if specified) to the C++ index)
# string array possible_args_list; (a list of space separated indexes)
# string in_module; e.g. Gtk
@@ -75,7 +80,7 @@ sub new($$)
$$self{param_types} = [];
$$self{param_names} = [];
$$self{param_default_values} = [];
- $$self{param_optional} = [];
+ $$self{param_flags} = [];
$$self{param_mappings} = {};
$$self{possible_args_list} = [];
$$self{in_module} = "";
@@ -136,7 +141,7 @@ sub new_ctor($$)
$$self{param_types} = [];
$$self{param_names} = [];
$$self{param_default_values} = [];
- $$self{param_optional} = [];
+ $$self{param_flags} = [];
$$self{param_mappings} = {};
$$self{possible_args_list} = [];
$$self{in_module} = "";
@@ -186,13 +191,13 @@ sub parse_param($$)
my $value = "";
my $id = 0;
my $has_value = 0;
- my $is_optional = 0;
+ my $flags = 0;
my $curr_param = 0;
my $param_types = $$self{param_types};
my $param_names = $$self{param_names};
my $param_default_values = $$self{param_default_values};
- my $param_optional = $$self{param_optional};
+ my $param_flags = $$self{param_flags};
my $param_mappings = $$self{param_mappings};
# Mappings from a C name to this C++ param defaults to empty (no mapping).
@@ -206,7 +211,7 @@ sub parse_param($$)
# parse through argument list
my @str = ();
my $par = 0;
- foreach (split(/(const )|([,=&*()])|(<[^,]*>)|(\s+)/, $line)) #special characters OR <something> OR whitespace.
+ foreach (split(/(const )|([,=&*()])|(<[^,{}]*>)|(\s+)/, $line)) #special characters OR <something> OR whitespace.
{
next if ( !defined($_) or $_ eq "" );
@@ -222,7 +227,7 @@ sub parse_param($$)
$par--; #Decrement the number of parameters.
next;
}
- elsif ( $par || /^(const )|(<[^,]*>)|([*&])|(\s+)/ ) #TODO: What's happening here?
+ elsif ( $par || /^(const )|(<[^,{}]*>)|([*&])|(\s+)/ ) #TODO: What's happening here?
{
push(@str, $_); #This looks like part of the type, so we store it.
next;
@@ -252,21 +257,24 @@ sub parse_param($$)
$type = string_trim($type);
- # Determine if the param is optional or if a C param name should be
- # mapped to the current C++ index (if name ends with {c_name?}). (A
- # '.' for the name means use the C++ as the C name).
- if ($name =~ /\{\s*(\w*|\.)\s*(\??)\s*\}$/)
+ # Determine if the param is optional, an output param or if a C param
+ # name should be mapped to the current C++ index (if name ends with
+ # {c_name>>?}). (A '.' for the name means use the C++ as the C name).
+ # '@' - Means that it is an output parameter.
+ # '?' - Means that it is an optional parameter.
+ if ($name =~ /\{\s*(\w+|\.)?\s*(>>)?\s*(\??)\s*\}$/)
{
- $is_optional = 1 if($2);
+ $flags = FLAG_PARAM_OPTIONAL if($3);
+ $flags |= FLAG_PARAM_OUTPUT if($2);
$mapping = $1 if($1);
- $name =~ s/\{\s*(\w|\.)*\??\s*\}$//;
+ $name =~ s/\{\s*(\w+|\.)?\s*(>>)?\s*\??\s*\}$//;
$mapping = $name if($mapping eq ".");
}
push(@$param_types, $type);
push(@$param_names, $name);
push(@$param_default_values, $value);
- push(@$param_optional, $is_optional);
+ push(@$param_flags, $flags);
# Map from the c_name to the C++ index (no map if no name given).
$$param_mappings{$mapping} = $curr_param if($mapping);
@@ -277,7 +285,7 @@ sub parse_param($$)
$value = "";
$has_value = 0;
$name = "";
- $is_optional = 0;
+ $flags = 0;
$curr_param++;
# Mappings from a C name to this C++ param defaults to empty (no mapping).
@@ -323,22 +331,23 @@ sub parse_param($$)
}
$type = string_trim($type);
-
- # Determine if the param is optional or if a C param name should be
- # mapped to the current C++ index (if name ends with {c_name?}). (A
- # '.' for the name means use the C++ as the C name).
- if ($name =~ /\{\s*(\w*|\.)\s*(\??)\s*\}$/)
+
+ # Determine if the param is optional, an output param or if a C param
+ # name should be mapped to the current C++ index (if name ends with
+ # {c_name>>?}). (A '.' for the name means use the C++ as the C name).
+ if ($name =~ /\{\s*(\w+|\.)?\s*(>>)?\s*(\??)\s*\}$/)
{
- $is_optional = 1 if($2);
+ $flags = FLAG_PARAM_OPTIONAL if($3);
+ $flags |= FLAG_PARAM_OUTPUT if($2);
$mapping = $1 if($1);
- $name =~ s/\{\s*(\w*|\.)\??\s*\}$//;
+ $name =~ s/\{\s*(\w+|\.)?\s*(>>)?\??\s*\}$//;
$mapping = $name if($mapping eq ".");
}
push(@$param_types, $type);
push(@$param_names, $name);
push(@$param_default_values, $value);
- push(@$param_optional, $is_optional);
+ push(@$param_flags, $flags);
# Map from the c_name to the C++ index (no map if no name given).
$$param_mappings{$mapping} = $curr_param if($mapping);
@@ -434,7 +443,7 @@ sub possible_args_list($$)
my $param_names = $$self{param_names};
my $param_types = $$self{param_types};
- my $param_optional = $$self{param_optional};
+ my $param_flags = $$self{param_flags};
my @result = ();
@@ -455,7 +464,7 @@ sub possible_args_list($$)
push(@result, "$i");
# And if it's optional also add an empty string to represent that it is
# not added.
- push(@result, "") if ($$param_optional[$i]);
+ push(@result, "") if ($$param_flags[$i] & FLAG_PARAM_OPTIONAL);
return @result;
}
@@ -477,7 +486,7 @@ sub possible_args_list($$)
# If this parameter is optional, append the remaining possibilities without
# this param's type and name.
- if($$param_optional[$i])
+ if($$param_flags[$i] & FLAG_PARAM_OPTIONAL)
{
foreach my $possibility (@remaining)
{
diff --git a/tools/pm/Output.pm b/tools/pm/Output.pm
index 2cad5d82..a820d240 100644
--- a/tools/pm/Output.pm
+++ b/tools/pm/Output.pm
@@ -19,6 +19,7 @@
package Output;
use strict;
use open IO => ":utf8";
+use Function qw(FLAG_PARAM_OPTIONAL FLAG_PARAM_OUTPUT);
use DocsParser;
@@ -84,23 +85,23 @@ sub error
sub ifdef($$)
{
- my ($self, $ifdef) = @_;
- if ($ifdef)
- {
- $self->append("\n#ifdef $ifdef\n");
- }
+ my ($self, $ifdef) = @_;
+ if ($ifdef)
+ {
+ $self->append("\n#ifdef $ifdef\n");
+ }
}
sub endif($$)
{
- my ($self, $ifdef) = @_;
- if ($ifdef)
- {
- $self->append("\n#endif // $ifdef\n");
- }
+ my ($self, $ifdef) = @_;
+ if ($ifdef)
+ {
+ $self->append("\n#endif // $ifdef\n");
+ }
}
-### Convert _WRAP to a virtual
+### Convert _WRAP to a virtual
# _VFUNC_H(signame,rettype,`<cppargs>')
# _VFUNC_PH(gtkname,crettype,cargs and names)
# void output_wrap_vfunc_h($filename, $line_num, $objCppfunc, $objCDefsFunc)
@@ -162,13 +163,16 @@ sub output_wrap_vfunc_cc($$$$$$$$)
my $refreturn = "";
$refreturn = "refreturn" if($$objCppfunc{rettype_needs_ref});
+ my ($conversions, $declarations, $initializations) =
+ convert_args_cpp_to_c($objCppfunc, $objCFunc, 0, $line_num, $errthrow);
+
my $str = sprintf("_VFUNC_CC(%s,%s,%s,%s,\`%s\',\`%s\',%s,%s,%s,%s)dnl\n",
$$objCppfunc{name},
$cname,
$$objCppfunc{rettype},
$$objCFunc{rettype},
$objCppfunc->args_types_and_names(),
- convert_args_cpp_to_c($objCppfunc, $objCFunc, 0, $line_num, $errthrow), #$objCppfunc->args_names_only(),
+ $conversions,
$objCppfunc->get_is_const(),
$refreturn,
$ifdef,
@@ -375,14 +379,19 @@ sub output_wrap_meth($$$$$$$)
#Implementation:
my $str;
if ($$objCppfunc{static}) {
- $str = sprintf("_STATIC_METHOD(%s,%s,`%s\',%s,\`%s\',\`%s\',%s,%s,%s,%s,%s,%s,%s)dnl\n",
+ my ($conversions, $declarations, $initializations) =
+ convert_args_cpp_to_c($objCppfunc, $objCDefsFunc, 1, $line_num,
+ $errthrow, $arg_list); #1 means it's static, so it has 'object'.
+
+ $str = sprintf("_STATIC_METHOD(%s,%s,\`%s\',%s,\`%s\',\`%s\',\`%s\',\`%s\',%s,%s,%s,%s,%s,%s,%s)dnl\n",
$$objCppfunc{name},
$$objCDefsFunc{c_name},
$$objCppfunc{rettype},
$objCDefsFunc->get_return_type_for_methods(),
$objCppfunc->args_types_and_names($arg_list),
- convert_args_cpp_to_c($objCppfunc, $objCDefsFunc, 1, $line_num,
- $errthrow, $arg_list), #1 means it's static, so it has 'object'.
+ $declarations,
+ $conversions,
+ $initializations,
$refneeded,
$errthrow,
$deprecated,
@@ -392,14 +401,19 @@ sub output_wrap_meth($$$$$$$)
$line_num
);
} else {
- $str = sprintf("_METHOD(%s,%s,`%s\',%s,\`%s\',\`%s\',%s,%s,%s,%s,%s,\`%s\',%s,%s,%s,%s)dnl\n",
+ my ($conversions, $declarations, $initializations) =
+ convert_args_cpp_to_c($objCppfunc, $objCDefsFunc, 0, $line_num,
+ $errthrow, $arg_list);
+
+ $str = sprintf("_METHOD(%s,%s,\`%s\',%s,\`%s\',\`%s\',\`%s\',\`%s\',%s,%s,%s,%s,%s,\`%s\',%s,%s,%s,%s)dnl\n",
$$objCppfunc{name},
$$objCDefsFunc{c_name},
$$objCppfunc{rettype},
$objCDefsFunc->get_return_type_for_methods(),
$objCppfunc->args_types_and_names($arg_list),
- convert_args_cpp_to_c($objCppfunc, $objCDefsFunc, 0, $line_num,
- $errthrow, $arg_list),
+ $declarations,
+ $conversions,
+ $initializations,
$$objCppfunc{const},
$refneeded,
$errthrow,
@@ -824,8 +838,12 @@ sub remove_temp_files($)
-# procedure for generating CONVERT macros
-# $string convert_args_cpp_to_c($objCppfunc, $objCDefsFunc, $static, $wrap_line_number,$automatic_error, $index = 0)
+# procedure for generating CONVERT macros, C declarations (for C output
+# variables), and INITIALIZE macros (to set the corresponding C++ parameters
+# from the C output parameters) for the specified argument list
+# (string, string, string) convert_args_cpp_to_c($objCppfunc, $objCDefsFunc, $static, $wrap_line_number,$automatic_error, $index = 0)
+# The return is an array of 3 strings: The _CONVERT macros, the C declarations
+# and the _INITIALIZE macros.
# The optional index specifies which arg list out of the possible combination
# of arguments based on whether any arguments are optional. index = 0 ==> all
# the arguments.
@@ -838,12 +856,14 @@ sub convert_args_cpp_to_c($$$$$)
my $cpp_param_names = $$objCppfunc{param_names};
my $cpp_param_types = $$objCppfunc{param_types};
- my $cpp_param_optional = $$objCppfunc{param_optional};
+ my $cpp_param_flags = $$objCppfunc{param_flags};
my $cpp_param_mappings = $$objCppfunc{param_mappings};
my $c_param_types = $$objCDefsFunc{param_types};
my $c_param_names = $$objCDefsFunc{param_names};
- my @result;
+ my @conversions;
+ my @declarations;
+ my @initializations;
my $num_c_args_expected = scalar(@{$c_param_types});
if( !($static) ) { $num_c_args_expected--; } #The cpp method will need an Object* paramater at the start.
@@ -871,7 +891,7 @@ sub convert_args_cpp_to_c($$$$$)
$num_cpp_args++;
$cpp_param_names = [@{$cpp_param_names},"gerror"];
$cpp_param_types = [@{$cpp_param_types},"GError*&"];
- $cpp_param_optional = [@{$cpp_param_optional}, 0];
+ $cpp_param_flags = [@{$cpp_param_flags}, 0];
# Map from the C gerror param name to the newly added C++ param index.
# The correct C++ index to map to (from the C name) depends on if there
@@ -889,10 +909,10 @@ sub convert_args_cpp_to_c($$$$$)
$objCppfunc->dump();
$objCDefsFunc->dump();
- return "";
+ return ("", "", "");
}
- # If there is an output variable it must be processed so re-increment (now)
+ # If there is an output parameter it must be processed so re-increment (now)
# the number of C++ arguments.
$num_cpp_args++ if($has_output_param);
@@ -932,18 +952,40 @@ sub convert_args_cpp_to_c($$$$$)
# If the C++ index is not found in the list of desired parameters, pass
# NULL to the C func unless the param is not optional (applies to a
# possibly added GError parameter).
- if ($$cpp_param_optional[$cpp_param_index])
+ if (($$cpp_param_flags[$cpp_param_index] & FLAG_PARAM_OPTIONAL))
{
- push(@result, "0");
+ push(@conversions, "0");
next;
}
}
+ if ($$cpp_param_flags[$cpp_param_index] & FLAG_PARAM_OUTPUT)
+ {
+ # Get a generic name for the C output parameter name.
+ my $cOutputParamName = "g_" . $$c_param_names[$iCParam];
+ my $cOutputParamType = $cParamType;
+ # Remove a possible final '*' from the output parameter type because it
+ # will be passed by C reference (&name).
+ $cOutputParamType =~ s/\*$//;
+
+ push(@declarations, " $cOutputParamType $cOutputParamName = 0;");
+
+ push(@conversions, "&" . $cOutputParamName);
+
+ push(@initializations, sprintf(" _INITIALIZE(\`%s\',%s,%s,%s,%s);",
+ $cppParamType,
+ $cOutputParamType,
+ $cppParamName,
+ $cOutputParamName,
+ $wrap_line_number));
+ next;
+ }
+
if ($cppParamType ne $cParamType) #If a type conversion is needed.
{
- push(@result, sprintf("_CONVERT(%s,%s,%s,%s)",
+ push(@conversions, sprintf("_CONVERT(%s,%s,%s,%s)",
$cppParamType,
$cParamType,
$cppParamName,
@@ -951,11 +993,12 @@ sub convert_args_cpp_to_c($$$$$)
}
else
{
- push(@result, $cppParamName);
+ push(@conversions, $cppParamName);
}
}
- return join(", ", @result);
+ return ( join(", ", @conversions), join("\n ", @declarations),
+ join("\n ", @initializations) );
}
# procedure for generating CONVERT macros
@@ -1039,7 +1082,7 @@ sub get_ctor_properties($$$$$)
my $cpp_param_names = $$objCppfunc{param_names};
my $cpp_param_types = $$objCppfunc{param_types};
- my $cpp_param_optional = $$objCppfunc{param_optional};
+ my $cpp_param_flags = $$objCppfunc{param_flags};
my $cpp_param_mappings = $$objCppfunc{param_mappings};
my $c_param_types = $$objCDefsFunc{param_types};
my $c_param_names = $$objCDefsFunc{param_names};
@@ -1084,7 +1127,7 @@ sub get_ctor_properties($$$$$)
{
# If the C++ index is not found in the list of desired parameters, pass
# NULL to the C func unless the param is not optional.
- if ($$cpp_param_optional[$cpp_param_index])
+ if (~($$cpp_param_flags[$cpp_param_index] & FLAG_PARAM_OPTIONAL))
{
push(@result, "0");
next;
@@ -1131,8 +1174,8 @@ sub output_implements_interface($$)
my ($self, $interface, $ifdef) = @_;
my $str = sprintf("_IMPLEMENTS_INTERFACE_CC(%s, %s)dnl\n",
- $interface,
- $ifdef);
+ $interface,
+ $ifdef);
$self->append($str);
}
diff --git a/tools/pm/WrapParser.pm b/tools/pm/WrapParser.pm
index 3841fee4..e55479b4 100644
--- a/tools/pm/WrapParser.pm
+++ b/tools/pm/WrapParser.pm
@@ -681,16 +681,25 @@ sub string_split_commas($)
my @out;
my $level = 0;
+ my $in_braces = 0;
my $str = "";
- my @in = split(/([,()<>])/, $in);
+ my @in = split(/([,()<>{}])/, $in);
while ($#in > -1)
{
my $t = shift @in;
next if ($t eq "");
+
+ $in_braces++ if ($t eq "{");
+ $in_braces-- if ($t eq "}");
+
$level++ if ($t eq "(" or $t eq "<");
- $level-- if ($t eq ")" or $t eq ">");
+
+ # In the case of a '>' decrease the level if it is not in a {...}
+ # because if it is found in a {...} it is most likely indicating that
+ # a parameter in a method declaration is an output param.
+ $level-- if ($t eq ")" or ($t eq ">" && !$in_braces));
# skip , inside functions Ie. void (*)(int,int)
if ( ($t eq ",") && !$level)