diff options
author | José Alburquerque <jaalburqu@svn.gnome.org> | 2012-09-18 15:22:25 -0400 |
---|---|---|
committer | José Alburquerque <jaalburqu@svn.gnome.org> | 2012-09-18 15:22:25 -0400 |
commit | 63cae37cd9dde19ffffe6d1b40c6bbb300f04a97 (patch) | |
tree | 5ba7319a65b0145780aaa1427440ebd4bbdaaf6c | |
parent | 415d91884cd3300f3cb6836f4b7fdc5364e734b3 (diff) | |
download | glibmm-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-- | ChangeLog | 62 | ||||
-rw-r--r-- | tools/m4/convert_base.m4 | 3 | ||||
-rw-r--r-- | tools/m4/convert_gio.m4 | 1 | ||||
-rw-r--r-- | tools/m4/method.m4 | 162 | ||||
-rw-r--r-- | tools/pm/Function.pm | 63 | ||||
-rw-r--r-- | tools/pm/Output.pm | 111 | ||||
-rw-r--r-- | tools/pm/WrapParser.pm | 13 |
7 files changed, 293 insertions, 122 deletions
@@ -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) |