diff options
Diffstat (limited to 'tools/pm')
-rw-r--r-- | tools/pm/DocsParser.pm | 257 | ||||
-rw-r--r-- | tools/pm/Enum.pm | 2 | ||||
-rw-r--r-- | tools/pm/Output.pm | 120 | ||||
-rw-r--r-- | tools/pm/Property.pm | 10 | ||||
-rw-r--r-- | tools/pm/WrapParser.pm | 153 |
5 files changed, 392 insertions, 150 deletions
diff --git a/tools/pm/DocsParser.pm b/tools/pm/DocsParser.pm index c771fc3c..8dae9c14 100644 --- a/tools/pm/DocsParser.pm +++ b/tools/pm/DocsParser.pm @@ -25,7 +25,7 @@ use XML::Parser; use strict; use warnings; -# use Util; +use Util; use Function; use GtkDefs; use Object; @@ -112,18 +112,19 @@ sub parse_on_start($$%) $tag = lc($tag); - if($tag eq "function" or $tag eq "signal" or $tag eq "enum") + if($tag eq "function" or $tag eq "signal" or $tag eq "property" or $tag eq "enum") { if(defined $DocsParser::objCurrentFunction) { $objParser->xpcroak( - "\nClose a function, signal or enum tag before you open another one."); + "\nClose a function, signal, property or enum tag before you open another one."); } my $functionName = $attr{name}; - # Change signal name from Class::a-signal-name to Class::a_signal_name. - $functionName =~ s/-/_/g if($tag eq "signal"); + # Change signal name from Class::a-signal-name to Class::a_signal_name + # and property name from Class:a-property-name to Class:a_property_name + $functionName =~ s/-/_/g if ($tag eq "signal" or $tag eq "property"); #Reuse existing Function, if it exists: #(For instance, if this is the override parse) @@ -195,7 +196,7 @@ sub parse_on_end($$) $tag = lc($tag); - if($tag eq "function" or $tag eq "signal" or $tag eq "enum") + if($tag eq "function" or $tag eq "signal" or $tag eq "property" or $tag eq "enum") { # Store the Function structure in the array: my $functionName = $$DocsParser::objCurrentFunction{name}; @@ -233,14 +234,15 @@ sub parse_on_cdata($$) } } -sub lookup_enum_documentation($$$) +sub lookup_enum_documentation($$$$) { - my ($c_enum_name, $cpp_enum_name, $ref_flags) = @_; + my ($c_enum_name, $cpp_enum_name, $indent, $ref_flags) = @_; my @subst_in = []; my @subst_out = []; + my $newin = ""; - # Get the substitutions. + # Get the substitutions, and recognize some flags too. foreach(@$ref_flags) { if(/^\s*s#([^#]+)#([^#]*)#\s*$/) @@ -248,6 +250,10 @@ sub lookup_enum_documentation($$$) push(@subst_in, $1); push(@subst_out, $2); } + elsif(/^\s*newin(.*)/) #If newin is at the start. + { + $newin = string_unquote(string_trim($1)); + } } my $objFunction = $DocsParser::hasharrayFunctions{$c_enum_name}; @@ -285,19 +291,23 @@ sub lookup_enum_documentation($$$) $param =~ s/([a-zA-Z0-9]*(_[a-zA-Z0-9]+)*)_?/$1/g; if(length($desc) > 0) { - $desc =~ s/\n/ /g; - $desc =~ s/ $//; - $desc =~ s/^\s+//; # Chop off leading whitespace + # Chop off leading and trailing whitespace. + $desc =~ s/^\s+//; + $desc =~ s/\s+$//; $desc .= '.' unless($desc =~ /(?:^|\.)$/); - $docs .= "\@var $cpp_enum_name ${param}\n \u${desc}\n\n"; # \u = Convert next char to uppercase + $docs .= "\@var $cpp_enum_name ${param}\n\u${desc}\n\n"; # \u = Convert next char to uppercase } } - # Append the enum description docs. - $docs .= "\@enum $cpp_enum_name\n"; - $docs .= $$objFunction{description}; + # Replace @newin in the enum description, but don't in the element descriptions. + my $description = "\@enum $cpp_enum_name\n"; + $description .= $$objFunction{description}; + DocsParser::convert_docs_to_cpp($objFunction, \$description); + DocsParser::replace_or_add_newin(\$description, $newin); + # Append the enum description docs. DocsParser::convert_docs_to_cpp($objFunction, \$docs); + $docs .= "\n\n$description"; DocsParser::add_m4_quotes(\$docs); # Escape the space after "i.e." or "e.g." in the brief description. @@ -305,20 +315,21 @@ sub lookup_enum_documentation($$$) remove_example_code($c_enum_name, \$docs); - # Convert to Doxygen-style comment. - $docs =~ s/\n/\n \* /g; - $docs = "\/\*\* " . $docs; + # Add indentation and an asterisk on all lines except the first. + # $docs does not contain leading "/**" and trailing "*/". + $docs =~ s/\n/\n${indent}\* /g; return $docs; } -# $strCommentBlock lookup_documentation($strFunctionName, $deprecation_docs, $objCppfunc) +# $strCommentBlock lookup_documentation($strFunctionName, $deprecation_docs, $newin, $objCppfunc) # The final objCppfunc parameter is optional. If passed, it is used to # decide if the final C parameter should be omitted if the C++ method -# has a slot parameter. -sub lookup_documentation($$;$) +# has a slot parameter. It is also used for converting C parameter names to +# C++ parameter names in the documentation, if they differ. +sub lookup_documentation($$$;$) { - my ($functionName, $deprecation_docs, $objCppfunc) = @_; + my ($functionName, $deprecation_docs, $newin, $objCppfunc) = @_; my $objFunction = $DocsParser::hasharrayFunctions{$functionName}; if(!$objFunction) @@ -335,18 +346,30 @@ sub lookup_documentation($$;$) } DocsParser::convert_docs_to_cpp($objFunction, \$text); + DocsParser::replace_or_add_newin(\$text, $newin); # A blank line, marking the end of a paragraph, is needed after @newin. # Most @newins are at the end of a function description. $text .= "\n"; - #Add note about deprecation if we have specified that in our _WRAP_METHOD() call: + # Add note about deprecation if we have specified that in our _WRAP_METHOD(), + # _WRAP_SIGNAL(), _WRAP_PROPERTY() or _WRAP_CHILD_PROPERTY() call: if($deprecation_docs ne "") { $text .= "\n\@deprecated $deprecation_docs\n"; } - DocsParser::append_parameter_docs($objFunction, \$text, $objCppfunc); + my %param_name_mappings = DocsParser::append_parameter_docs($objFunction, \$text, $objCppfunc); DocsParser::append_return_docs($objFunction, \$text); + + # Convert C parameter names to C++ parameter names where they differ. + foreach my $key (keys %param_name_mappings) + { + $text =~ s/\@(param|a) $key\b/\@$1 $param_name_mappings{$key}/g; + } + + # Remove leading and trailing white space. + $text = string_trim($text); + DocsParser::add_m4_quotes(\$text); # Escape the space after "i.e." or "e.g." in the brief description. @@ -375,7 +398,8 @@ sub remove_example_code($$) ($$text =~ s"<programlisting>.*?</programlisting>"\n[C example ellipted]"sg); $example_removals += ($$text =~ s"\|\[.*?]\|"\n[C example ellipted]"sg); - print STDERR "gmmproc: $main::source: $obj_name: Example code discarded.\n" + # See "MS Visual Studio" comment in gmmproc.in. + print STDERR "gmmproc, $main::source, $obj_name: Example code discarded.\n" if ($example_removals); } @@ -396,51 +420,143 @@ sub add_m4_quotes($) # The final objCppfunc is optional. If passed, it is used to determine # if the final C parameter should be omitted if the C++ method has a -# slot parameter. +# slot parameter. It is also used for converting C parameter names to +# C++ parameter names in the documentation, if they differ. sub append_parameter_docs($$;$) { my ($obj_function, $text, $objCppfunc) = @_; - my @param_names = @{$$obj_function{param_names}}; + my @docs_param_names = @{$$obj_function{param_names}}; my $param_descriptions = \$$obj_function{param_descriptions}; - - # Strip first parameter if this is a method. my $defs_method = GtkDefs::lookup_method_dont_mark($$obj_function{name}); - # the second alternative is for use with method-mappings meaning: - # this function is mapped into this Gtk::class - shift(@param_names) if(($defs_method && $$defs_method{class} ne "") || - ($$obj_function{mapped_class} ne "")); + my @c_param_names = $defs_method ? @{$$defs_method{param_names}} : @docs_param_names; + + # The information in + # $obj_function comes from the docs.xml file, + # $objCppfunc comes from _WRAP_METHOD() or _WRAP_SIGNAL() in the .hg file, + # $defs_method comes from the methods.defs file. + + # Ideally @docs_param_names and @c_param_names are identical. + # In the real world the parameters in the C documentation are sometimes not + # listed in the same order as the arguments in the C function declaration. + # We try to handle that case to some extent. If no argument name is misspelt + # in either the docs or the C function declaration, it usually succeeds for + # methods, but not for signals. For signals there is no C function declaration + # to compare with. If the docs of some method or signal get badly distorted + # due to imperfections in the C docs, and it's difficult to get the C docs + # corrected, correct docs can be added to the docs_override.xml file. + + # Skip first param if this is a signal. + if ($$obj_function{name} =~ /\w+::/) + { + shift(@docs_param_names); + shift(@c_param_names); + } + # Skip first parameter if this is a non-static method. + elsif (defined($objCppfunc)) + { + if (!$$objCppfunc{static}) + { + shift(@docs_param_names); + shift(@c_param_names); + } + } + # The second alternative is for use with method-mappings meaning: + # this function is mapped into this Gtk::class. + elsif (($defs_method && $$defs_method{class} ne "") || + $$obj_function{mapped_class} ne "") + { + shift(@docs_param_names); + shift(@c_param_names); + } - # Also skip first param if this is a signal. - shift(@param_names) if ($$obj_function{name} =~ /\w+::/); # Skip the last param if there is a slot because it would be a # gpointer user_data parameter. - pop(@param_names) if (defined($objCppfunc) && $$objCppfunc{slot_name}); + if (defined($objCppfunc) && $$objCppfunc{slot_name}) + { + pop(@docs_param_names); + pop(@c_param_names); + } - foreach my $param (@param_names) + # Skip the last param if it's an error output param. + if (scalar @docs_param_names && $docs_param_names[-1] eq "error") + { + pop(@docs_param_names); + pop(@c_param_names); + } + + my $cpp_param_names; + my $param_mappings; + my $out_param_index = 1000; # No method has that many arguments, hopefully. + if (defined($objCppfunc)) { - if ($param ne "error" ) #We wrap GErrors as exceptions, so ignore these. + $cpp_param_names = $$objCppfunc{param_names}; + $param_mappings = $$objCppfunc{param_mappings}; # C name -> C++ index + if (exists $$param_mappings{OUT}) { - my $desc = $$param_descriptions->{$param}; + $out_param_index = $$param_mappings{OUT}; + } + } + my %param_name_mappings; # C name -> C++ name - # Deal with callback parameters converting the docs to a slot - # compatible format. - if ($param eq "callback") + for (my $i = 0; $i < @docs_param_names; ++$i) + { + my $param = $docs_param_names[$i]; + my $desc = $$param_descriptions->{$param}; + + if (defined($objCppfunc)) + { + # If the C++ name is not equal to the C name, mark that the name + # shall be changed in the documentation. + my $cpp_name = $param; + if (exists $$param_mappings{$param}) { - $param = "slot"; - $$text =~ s/\@a callback/\@a slot/g; + # Rename and/or reorder declaration ({c_name} or {.}) in _WRAP_*(). + $cpp_name = $$cpp_param_names[$$param_mappings{$param}]; } - - $param =~ s/([a-zA-Z0-9]*(_[a-zA-Z0-9]+)*)_?/$1/g; - DocsParser::convert_docs_to_cpp($obj_function, \$desc); - if(length($desc) > 0) + elsif ($c_param_names[$i] eq $param) + { + # Location in docs coincides with location in C declaration. + my $cpp_index = $i; + $cpp_index++ if ($i >= $out_param_index); + $cpp_name = $$cpp_param_names[$cpp_index]; + } + else + { + # Search for the param in the C declaration. + for (my $j = 0; $j < @c_param_names; ++$j) + { + if ($c_param_names[$j] eq $param) + { + my $cpp_index = $j; + $cpp_index++ if ($j >= $out_param_index); + $cpp_name = $$cpp_param_names[$cpp_index]; + last; + } + } + } + if ($cpp_name ne $param) { - $desc .= '.' unless($desc =~ /(?:^|\.)$/); - $$text .= "\n\@param ${param} \u${desc}"; + $param_name_mappings{$param} = $cpp_name; } } + elsif ($param eq "callback") + { + # Deal with callback parameters converting the docs to a slot + # compatible format. + $param_name_mappings{$param} = "slot"; + } + + $param =~ s/([a-zA-Z0-9]*(_[a-zA-Z0-9]+)*)_?/$1/g; + DocsParser::convert_docs_to_cpp($obj_function, \$desc); + if(length($desc) > 0) + { + $desc .= '.' unless($desc =~ /(?:^|\.)$/); + $$text .= "\n\@param ${param} \u${desc}"; + } } + return %param_name_mappings; } @@ -513,14 +629,20 @@ sub convert_tags_to_doxygen($) s"<variablelist>\n?(.*?)</variablelist>\n?"&DocsParser::convert_variablelist($1)"esg; # Use our Doxygen @newin alias. - # If Since is not followed by a colon, substitute @newin only if it's - # in a sentence of its own at the end of the string. - s/\bSince:\s*(\d+)\.(\d+)\.(\d+)\b\.?/\@newin{$1,$2,$3}/g; - s/\bSince:\s*(\d+)\.(\d+)\b\.?/\@newin{$1,$2}/g; - s/(\.\s+)Since\s+(\d+)\.(\d+)\.(\d+)\.?$/$1\@newin{$2,$3,$4}/; - s/(\.\s+)Since\s+(\d+)\.(\d+)\.?$/$1\@newin{$2,$3}/; - - s"\b->\b"->"g; + # Accept "Since" with or without a following colon. + # Require the Since clause to be + # - at the end of the string, + # - at the end of a line and followed by a blank line, or + # - followed by "Deprecated". + # If none of these requirements is met, "Since" may be embedded inside + # a function description, referring to only a part of the description. + # See e.g. g_date_time_format() and gdk_cursor_new_from_pixbuf(). + # Doxygen assumes that @newin is followed by a paragraph that describes + # what is new, but we don't use it that way. + my $first_part = '\bSince[:\h]\h*(\d+)\.(\d+)'; # \h == [\t ] (horizontal whitespace) + my $last_part = '\.?(\s*$|\h*\n\h*\n|\s+Deprecated)'; + s/$first_part\.(\d+)$last_part/\@newin{$1,$2,$3}$4/g; + s/$first_part$last_part/\@newin{$1,$2}$3/g; # Doxygen is too dumb to handle — s"—" \@htmlonly—\@endhtmlonly "g; @@ -540,6 +662,21 @@ sub convert_tags_to_doxygen($) } } +# void replace_or_add_newin(\$text, $newin) +# If $newin is not empty, replace the version numbers in an existing @newin +# Doxygen alias, or add one if there is none. +sub replace_or_add_newin($$) +{ + my ($text, $newin) = @_; + + return if ($newin eq ""); + + if (!($$text =~ s/\@newin\{[\d,]+\}/\@newin{$newin}/)) + { + $$text .= "\n\n\@newin{$newin}"; + } +} + # Convert <simplelist> tags to a list of newline-separated elements. sub convert_simplelist($) { @@ -691,7 +828,7 @@ sub lookup_object_of_method($$) } else { - print "DocsParser.pm:lookup_object_of_method(): Warning: GtkDefs::lookup_object() failed for object name=" . $object . ", function name=" . $name . "\n"; + print "DocsParser.pm: lookup_object_of_method(): Warning: GtkDefs::lookup_object() failed for object name=" . $object . ", function name=" . $name . "\n"; print " This may be a missing define-object in a *.defs file.\n" } } diff --git a/tools/pm/Enum.pm b/tools/pm/Enum.pm index 8d0ce774..61840771 100644 --- a/tools/pm/Enum.pm +++ b/tools/pm/Enum.pm @@ -300,7 +300,7 @@ sub build_element_list($$$$) push(@subst_in, $1); push(@subst_out, $2); } - elsif($_ !~ /^\s*$/) + elsif($_ !~ /^\s*(?:newin.*)?$/) # newin or only white space { return undef; } diff --git a/tools/pm/Output.pm b/tools/pm/Output.pm index 05e0fa16..587d06ba 100644 --- a/tools/pm/Output.pm +++ b/tools/pm/Output.pm @@ -72,15 +72,16 @@ sub output_wrap_failed($$$) { my ($self, $cname, $error) = @_; + # See "MS Visual Studio" comment in gmmproc.in. my $str = sprintf("//gtkmmproc error: %s : %s", $cname, $error); - print STDERR "Output.pm: $main::source: $cname : $error\n"; + print STDERR "Output.pm, $main::source, $cname : $error\n"; $self->append($str); } sub error { my $format=shift @_; - printf STDERR "Output.pm: $main::source: $format",@_; + printf STDERR "Output.pm, $main::source: $format",@_; } sub ifdef($$) @@ -204,6 +205,9 @@ sub output_wrap_vfunc_cc($$$$$$$$) my $refreturn_ctype = ""; $refreturn_ctype = "refreturn_ctype" if($$objCFunc{rettype_needs_ref}); + my $keep_return = ""; + $keep_return = "keep_return" if($$objCppfunc{keep_return}); + # Get the conversions. my $conversions = convert_args_c_to_cpp($objCFunc, $objCppfunc, $line_num); @@ -211,7 +215,7 @@ sub output_wrap_vfunc_cc($$$$$$$$) my $returnValue = $$objCppfunc{return_value}; my $exceptionHandler = $$objCppfunc{exception_handler}; - my $str = sprintf("_VFUNC_PCC(%s,%s,%s,%s,\`%s\',\`%s\',\`%s\',%s,%s,%s,%s,%s,%s,%s,%s)dnl\n", + my $str = sprintf("_VFUNC_PCC(%s,%s,%s,%s,\`%s\',\`%s\',\`%s\',%s,%s,%s,%s,%s,%s,%s,%s,%s)dnl\n", $$objCppfunc{name}, $cname, $$objCppfunc{rettype}, @@ -221,6 +225,7 @@ sub output_wrap_vfunc_cc($$$$$$$$) $conversions, ${$objCFunc->get_param_names()}[0], $refreturn_ctype, + $keep_return, $ifdef, $errthrow, $$objCppfunc{slot_type}, @@ -578,11 +583,14 @@ sub output_wrap_create($$$) } } -# void output_wrap_sig_decl($filename, $line_num, $objCSignal, $objCppfunc, $signal_name, $bCustomCCallback, $ifdef, $commentblock, $deprecated, $deprecation_docs, $exceptionHandler) -# custom_signalproxy_name is "" when no type conversion is required - a normal templates SignalProxy will be used instead. -sub output_wrap_sig_decl($$$$$$$$$$$) +# void output_wrap_sig_decl($filename, $line_num, $objCSignal, $objCppfunc, $signal_name, +# $bCustomCCallback, $ifdef, $commentblock, $deprecated, $deprecation_docs, +# $newin, $exceptionHandler, $detail_name, $bTwoSignalMethods) +sub output_wrap_sig_decl($$$$$$$$$$$$$$) { - my ($self, $filename, $line_num, $objCSignal, $objCppfunc, $signal_name, $bCustomCCallback, $ifdef, $commentblock, $deprecated, $deprecation_docs, $exceptionHandler) = @_; + my ($self, $filename, $line_num, $objCSignal, $objCppfunc, $signal_name, + $bCustomCCallback, $ifdef, $commentblock, $deprecated, $deprecation_docs, + $newin, $exceptionHandler, $detail_name, $bTwoSignalMethods) = @_; # _SIGNAL_PROXY(c_signal_name, c_return_type, `<c_arg_types_and_names>', # cpp_signal_name, cpp_return_type, `<cpp_arg_types>',`<c_args_to_cpp>', @@ -594,8 +602,8 @@ sub output_wrap_sig_decl($$$$$$$$$$$) $underscored_signal_name =~ s/-/_/g; # Get the existing signal documentation from the parsed docs. - my $documentation = - DocsParser::lookup_documentation("$$objCSignal{class}::$underscored_signal_name", $deprecation_docs); + my $documentation = DocsParser::lookup_documentation( + "$$objCSignal{class}::$underscored_signal_name", $deprecation_docs, $newin, $objCppfunc); # Create a merged Doxygen comment block for the signal from the looked up # docs (the block will also contain a prototype of the slot as an example). @@ -609,6 +617,9 @@ sub output_wrap_sig_decl($$$$$$$$$$$) { # Strip leading whitespace $doxycomment =~ s/^\s+//; + # Add a level of m4 quotes. Necessary if $commentblock contains __FT__ or __BT__. + # DocsParser::lookup_documentation() adds it in $documentation. + $commentblock = "`" . $commentblock . "'"; # We don't have something to add, so just use $commentblock with # opening and closing tokens added. @@ -629,7 +640,7 @@ sub output_wrap_sig_decl($$$$$$$$$$$) my $conversions = convert_args_c_to_cpp($objCSignal, $objCppfunc, $line_num); - my $str = sprintf("_SIGNAL_PROXY(%s,%s,\`%s\',%s,%s,\`%s\',\`%s\',\`%s\',%s,\`%s\',%s,%s)dnl\n", + my $str = sprintf("_SIGNAL_PROXY(%s,%s,\`%s\',%s,%s,\`%s\',\`%s\',\`%s\',%s,\`%s\',%s,%s,%s,%s)dnl\n", $signal_name, $$objCSignal{rettype}, $objCSignal->args_types_and_names_without_object(), @@ -641,7 +652,9 @@ sub output_wrap_sig_decl($$$$$$$$$$$) $deprecated, $doxycomment, $ifdef, - $exceptionHandler + $exceptionHandler, + $detail_name, # If a detailed name is supported (signal_name::detail_name) + $bTwoSignalMethods # If separate signal_xxx() methods for detailed and general name. ); $self->append($str); @@ -675,17 +688,10 @@ sub output_wrap_enum($$$$$$$) # Get the enum documentation from the parsed docs. my $enum_docs = - DocsParser::lookup_enum_documentation("$c_type", "$cpp_type", \@flags); - - # Remove initial Doxygen comment block start ('/**') from the enum docs - # to merge the passed in Doxygen comment block. - $enum_docs =~ s/\/\*\*\s+//g; - - # Make sure indentation of passed in comment is correct. - $comment =~ s/\n\s*\*/\n */g; + DocsParser::lookup_enum_documentation("$c_type", "$cpp_type", " ", \@flags); # Merge the passed in comment to the existing enum documentation. - $comment = $comment . "\n * " . $enum_docs; + $comment .= "\n * " . $enum_docs if $enum_docs ne ""; my $str = sprintf("_ENUM(%s,%s,%s,\`%s\',\`%s\',\`%s\')dnl\n", $cpp_type, @@ -706,7 +712,7 @@ sub output_wrap_enum_docs_only($$$$$$$) # Get the existing enum description from the parsed docs. my $enum_docs = - DocsParser::lookup_enum_documentation("$c_type", "$cpp_type", \@flags); + DocsParser::lookup_enum_documentation("$c_type", "$cpp_type", " ", \@flags); if($enum_docs eq "") { @@ -715,17 +721,10 @@ sub output_wrap_enum_docs_only($$$$$$$) } # Include the enum docs in the module's enum docs group. - $enum_docs .= "\n * \@ingroup ${module_canonical}Enums\n"; + $enum_docs .= "\n *\n * \@ingroup ${module_canonical}Enums"; - # Remove initial Doxygen comment block start ('/**') from the enum docs - # to merge the passed in Doxygen comment block. - $enum_docs =~ s/\/\*\*\s+//g; - # Merge the passed in comment to the existing enum documentation. - $comment = "\/\*\* " . $comment . "\n * " . $enum_docs . "\n */\n"; - - # Make sure indentation of passed in comment is correct. - $comment =~ s/\n\s*\*/\n */g; + $comment = "/** " . $comment . "\n * " . $enum_docs . "\n */\n"; $self->append($comment); } @@ -761,10 +760,7 @@ sub output_wrap_gerror($$$$$$$) # Get the enum documentation from the parsed docs. my $enum_docs = - DocsParser::lookup_enum_documentation("$c_enum", "Code", \@flags); - - # Make sure indentation of enum documentation is correct. - $enum_docs =~ s/\n\s*\*/\n \*/g; + DocsParser::lookup_enum_documentation("$c_enum", "Code", " ", \@flags); # Prevent Doxygen from auto-linking to a class called Error. $enum_docs =~ s/([^%])(Error code)/$1%$2/g; @@ -785,7 +781,8 @@ sub output_wrap_gerror($$$$$$$) # void output_wrap_any_property($filename, $line_num, $name, $cpp_type, $c_class, $deprecated, $deprecation_docs, $objProperty, $proxy_macro) sub output_wrap_any_property($$$$$$$$$$) { - my ($self, $filename, $line_num, $name, $cpp_type, $c_class, $deprecated, $deprecation_docs, $objProperty, $proxy_macro) = @_; + my ($self, $filename, $line_num, $name, $cpp_type, $c_class, $deprecated, + $deprecation_docs, $newin, $objProperty, $proxy_macro) = @_; my $objDefsParser = $$self{objDefsParser}; @@ -817,9 +814,44 @@ sub output_wrap_any_property($$$$$$$$$$) my $name_underscored = $name; $name_underscored =~ tr/-/_/; - # Get the property documentation, if any, and add m4 quotes. - my $documentation = $objProperty->get_docs($deprecation_docs); - add_m4_quotes(\$documentation) if ($documentation ne ""); + # Get the existing property documentation, if any, from the parsed docs. + my $documentation = DocsParser::lookup_documentation( + "$$objProperty{class}:$name_underscored", $deprecation_docs, $newin); + + if ($documentation ne "") + { + # Remove leading "/**" and trailing "*/". They will be added by the m4 macro. + $documentation =~ s/^\s*\/\*\*\s*//; + $documentation =~ s/\s*\*\/\s*$//; + } + + if ($documentation =~ /^`?[*\s]* + (?: + \@newin\{[\d,]+\} + |[Ss]ince[:\h]+\d+\.\d+ + |\@deprecated\s + |[Dd]eprecated[:\s] + )/x) + { + # The documentation begins with a "@newin", "Since", "@deprecated" or + # "Deprecated" line. Get documentation also from the Property object, + # but don't add another @newin or @deprecated. + my $objdoc = $objProperty->get_docs("", ""); + if ($objdoc ne "") + { + add_m4_quotes(\$objdoc); + $documentation = "$objdoc\n *\n * $documentation"; + } + } + elsif ($documentation eq "") + { + # Try to get the (usually short) documentation from the Property object. + $documentation = $objProperty->get_docs($deprecation_docs, $newin); + if ($documentation ne "") + { + add_m4_quotes(\$documentation); + } + } #Declaration: if($deprecated ne "") @@ -863,7 +895,8 @@ sub output_wrap_any_property($$$$$$$$$$) # void output_wrap_property($filename, $line_num, $name, $cpp_type, $deprecated, $deprecation_docs) sub output_wrap_property($$$$$$$$) { - my ($self, $filename, $line_num, $name, $cpp_type, $c_class, $deprecated, $deprecation_docs) = @_; + my ($self, $filename, $line_num, $name, $cpp_type, $c_class, $deprecated, + $deprecation_docs, $newin) = @_; my $objProperty = GtkDefs::lookup_property($c_class, $name); if($objProperty eq 0) #If the lookup failed: @@ -872,7 +905,8 @@ sub output_wrap_property($$$$$$$$) } else { - $self->output_wrap_any_property($filename, $line_num, $name, $cpp_type, $c_class, $deprecated, $deprecation_docs, $objProperty, "_PROPERTY_PROXY"); + $self->output_wrap_any_property($filename, $line_num, $name, $cpp_type, $c_class, + $deprecated, $deprecation_docs, $newin, $objProperty, "_PROPERTY_PROXY"); } } @@ -880,7 +914,8 @@ sub output_wrap_property($$$$$$$$) # void output_wrap_child_property($filename, $line_num, $name, $cpp_type, $deprecated, $deprecation_docs) sub output_wrap_child_property($$$$$$$$) { - my ($self, $filename, $line_num, $name, $cpp_type, $c_class, $deprecated, $deprecation_docs) = @_; + my ($self, $filename, $line_num, $name, $cpp_type, $c_class, $deprecated, + $deprecation_docs, $newin) = @_; my $objChildProperty = GtkDefs::lookup_child_property($c_class, $name); if($objChildProperty eq 0) #If the lookup failed: @@ -889,7 +924,8 @@ sub output_wrap_child_property($$$$$$$$) } else { - $self->output_wrap_any_property($filename, $line_num, $name, $cpp_type, $c_class, $deprecated, $deprecation_docs, $objChildProperty, "_CHILD_PROPERTY_PROXY"); + $self->output_wrap_any_property($filename, $line_num, $name, $cpp_type, $c_class, + $deprecated, $deprecation_docs, $newin, $objChildProperty, "_CHILD_PROPERTY_PROXY"); } } diff --git a/tools/pm/Property.pm b/tools/pm/Property.pm index f89140ea..8e2a131f 100644 --- a/tools/pm/Property.pm +++ b/tools/pm/Property.pm @@ -112,15 +112,21 @@ sub get_writable($) sub get_docs($$) { - my ($self, $deprecation_docs) = @_; + my ($self, $deprecation_docs, $newin) = @_; my $text = $$self{docs}; - #Add note about deprecation if we have specified that in our _WRAP_METHOD() call: + #Add note about deprecation if we have specified that in our _WRAP_PROPERTY() + #or_WRAP_CHILD_PROPERTY() call: if($deprecation_docs ne "") { $text .= "\n * \@deprecated $deprecation_docs"; } + if ($newin ne "") + { + $text .= "\n *\n * \@newin{$newin}"; + } + return $text; } diff --git a/tools/pm/WrapParser.pm b/tools/pm/WrapParser.pm index dc12eb47..b33ecb13 100644 --- a/tools/pm/WrapParser.pm +++ b/tools/pm/WrapParser.pm @@ -111,6 +111,8 @@ sub parse_and_build_output($) if ($token eq "_DEFS") { $self->on_defs(); next;} #Read the defs file. if ($token eq "_IGNORE") { $self->on_ignore(); next;} #Ignore a function. if ($token eq "_IGNORE_SIGNAL") { $self->on_ignore_signal(); next;} #Ignore a signal. + if ($token eq "_IGNORE_PROPERTY") { $self->on_ignore_property(); next;} #Ignore a property. + if ($token eq "_IGNORE_CHILD_PROPERTY") { $self->on_ignore_child_property(); next;} #Ignore a child property. if ($token eq "_WRAP_METHOD") { $self->on_wrap_method(); next;} if ($token eq "_WRAP_METHOD_DOCS_ONLY") { $self->on_wrap_method_docs_only(); next;} if ($token eq "_WRAP_CORBA_METHOD") { $self->on_wrap_corba_method(); next;} #Used in libbonobo*mm. @@ -471,25 +473,42 @@ sub on_ignore($) } } -sub on_ignore_signal($) +# void on_ignore_signal_or_property(\&lookup_function, $type) +sub on_ignore_signal_or_property($$$) { - my ($self) = @_; - my $objOutputter = $$self{objOutputter}; + my ($self, $lookup_function, $type) = @_; my $str = $self->extract_bracketed_text(); - $str = string_trim($str); - $str = string_unquote($str); my @args = split(/\s+|,/,$str); foreach (@args) { - next if ($_ eq ""); - my $objCsignal = GtkDefs::lookup_signal($$self{c_class}, $_); #Pretend that we've used it. - if(!$objCsignal) + my $name = string_unquote($_); + next if ($name eq ""); + my $objCentity = $lookup_function->($$self{c_class}, $name); #Pretend that we've used it. + if (!$objCentity) { - $objOutputter->output_wrap_failed($_, "ignored signal defs lookup failed"); + $$self{objOutputter}->output_wrap_failed($name, "ignored $type defs lookup failed"); } } } +sub on_ignore_signal($) +{ + my ($self) = @_; + $self->on_ignore_signal_or_property(\&GtkDefs::lookup_signal, "signal"); +} + +sub on_ignore_property($) +{ + my ($self) = @_; + $self->on_ignore_signal_or_property(\&GtkDefs::lookup_property, "property"); +} + +sub on_ignore_child_property($) +{ + my ($self) = @_; + $self->on_ignore_signal_or_property(\&GtkDefs::lookup_child_property, "child property"); +} + ######################################## ### we have certain macros we need to insert at end of statements # void on_class($, $strClassCommand) @@ -683,11 +702,12 @@ sub extract_bracketed_text($) ######################################## ### breaks up a string by commas (smart) -# @strings string_split_commas($string) -sub string_split_commas($) +# @strings string_split_commas($string [, $ignore_quotes]) +sub string_split_commas($;$) { - my ($in) = @_; + my ($in, $ignore_quotes) = @_; + $ignore_quotes = 2 unless defined $ignore_quotes; my @out; my $level = 0; my $in_braces = 0; @@ -701,10 +721,10 @@ sub string_split_commas($) next if ($t eq ""); - # TODO: Delete the test for scalar(@out) >= 2 when we can stop accepting + # TODO: Delete the test for scalar(@out) >= $ignore_quotes when we can stop accepting # .hg files with unpaired quotes, such as _WRAP_PROPERTY("text_column, int). # See also TODO in extract_bracketed_text(). - $in_quotes = !$in_quotes if ($t eq '"' and scalar(@out) >= 2); + $in_quotes = !$in_quotes if ($t eq '"' and scalar(@out) >= $ignore_quotes); if (!$in_quotes) { $in_braces++ if ($t eq "{"); @@ -931,6 +951,7 @@ sub on_wrap_method($) $$objCfunc{constversion} = 0; $$objCfunc{deprecated} = ""; my $deprecation_docs = ""; + my $newin = ""; my $ifdef; while($#args >= 2) # If the optional ref/err/deprecated arguments are there. { @@ -957,6 +978,10 @@ sub on_wrap_method($) $deprecation_docs = string_unquote(string_trim($1)); } } + elsif($argRef =~ /^newin(.*)/) #If newin is at the start. + { + $newin = string_unquote(string_trim($1)); + } elsif($argRef =~ /^ifdef(.*)/) #If ifdef is at the start. { $ifdef = $1; @@ -989,7 +1014,7 @@ sub on_wrap_method($) else { $commentblock = DocsParser::lookup_documentation($argCFunctionName, - $deprecation_docs, $objCppfunc); + $deprecation_docs, $newin, $objCppfunc); } $objOutputter->output_wrap_meth($filename, $line_num, $objCppfunc, $objCfunc, $argCppMethodDecl, $commentblock, $ifdef); @@ -1007,7 +1032,7 @@ sub on_wrap_method_docs_only($) my $line_num = $$self{line_num}; my $str = $self->extract_bracketed_text(); - my @args = string_split_commas($str); + my @args = string_split_commas($str, 1); my $entity_type = "method"; @@ -1038,8 +1063,8 @@ sub on_wrap_method_docs_only($) } } - # Extra ref needed? $$objCfunc{throw_any_errors} = 0; + my $newin = ""; while($#args >= 1) # If the optional ref/err arguments are there. { my $argRef = string_trim(pop @args); @@ -1047,11 +1072,14 @@ sub on_wrap_method_docs_only($) { $$objCfunc{throw_any_errors} = 1; } + elsif($argRef =~ /^newin(.*)/) #If newin is at the start. + { + $newin = string_unquote(string_trim($1)); + } } my $commentblock = ""; - $commentblock = DocsParser::lookup_documentation($argCFunctionName, ""); - + $commentblock = DocsParser::lookup_documentation($argCFunctionName, "", $newin); $objOutputter->output_wrap_meth_docs_only($filename, $line_num, $commentblock); } @@ -1205,10 +1233,13 @@ sub on_wrap_signal($$) my $bNoDefaultHandler = 0; my $bCustomCCallback = 0; my $bRefreturn = 0; - my $ifdef; + my $ifdef = ""; my $argDeprecated = ""; my $deprecation_docs = ""; + my $newin = ""; my $exceptionHandler = ""; + my $detail_name = ""; + my $bTwoSignalMethods = 0; while($#args >= 2) # If optional arguments are there. { @@ -1217,23 +1248,19 @@ sub on_wrap_signal($$) { $bCustomDefaultHandler = 1; } - - if($argRef eq "no_default_handler") + elsif($argRef eq "no_default_handler") { $bNoDefaultHandler = 1; } - - if($argRef eq "custom_c_callback") + elsif($argRef eq "custom_c_callback") { $bCustomCCallback = 1; } - - if($argRef eq "refreturn") + elsif($argRef eq "refreturn") { $bRefreturn = 1; } - - if($argRef =~ /^deprecated(.*)/) #If deprecated is at the start. + elsif($argRef =~ /^deprecated(.*)/) #If deprecated is at the start. { $argDeprecated = "deprecated"; @@ -1242,21 +1269,36 @@ sub on_wrap_signal($$) $deprecation_docs = string_unquote(string_trim($1)); } } - + elsif($argRef =~ /^newin(.*)/) #If newin is at the start. + { + $newin = string_unquote(string_trim($1)); + } elsif($argRef =~ /^ifdef(.*)/) #If ifdef is at the start. { $ifdef = $1; } - elsif($argRef =~ /^exception_handler\s+(.*)/) #If exception_handler at the start. { - $exceptionHandler = $1; + $exceptionHandler = $1; + } + elsif($argRef =~ /^detail_name\s+(.+)/) #If detail_name at the start. + { + $detail_name = $1; + } + elsif($argRef eq "two_signal_methods") + { + $bTwoSignalMethods = 1; + } + else + { + $self->error("_WRAP_SIGNAL: Invalid option '$argRef'.\n"); } } $self->output_wrap_signal($argCppDecl, $argCName, $$self{filename}, $$self{line_num}, $bCustomDefaultHandler, $bNoDefaultHandler, $bCustomCCallback, - $bRefreturn, $ifdef, $commentblock, $argDeprecated, $deprecation_docs, $exceptionHandler); + $bRefreturn, $ifdef, $commentblock, $argDeprecated, $deprecation_docs, + $newin, $exceptionHandler, $detail_name, $bTwoSignalMethods); } # void on_wrap_vfunc() @@ -1279,6 +1321,7 @@ sub on_wrap_vfunc($) $argCName = string_unquote($argCName); my $refreturn = 0; + my $keep_return = 0; my $refreturn_ctype = 0; my $returnValue = ""; my $exceptionHandler = ""; @@ -1299,6 +1342,12 @@ sub on_wrap_vfunc($) { $refreturn = 1; } + # Must a copy of the return value be kept, because the caller does not + # get its own copy? + elsif($argRef eq "keep_return") + { + $keep_return = 1; + } elsif($argRef eq "refreturn_ctype") { $refreturn_ctype = 1; @@ -1354,7 +1403,7 @@ sub on_wrap_vfunc($) } $self->output_wrap_vfunc($argCppDecl, $argCName, $$self{filename}, $$self{line_num}, - $refreturn, $refreturn_ctype, $custom_vfunc, + $refreturn, $keep_return, $refreturn_ctype, $custom_vfunc, $custom_vfunc_callback, $ifdef, $errthrow, $slot_name, $slot_callback, $no_slot_copy, $returnValue, $exceptionHandler); } @@ -1452,6 +1501,7 @@ sub on_wrap_any_property($) #TODO: Reduce duplication with on_wrap_method(): my $argDeprecated = ""; my $deprecation_docs = ""; + my $newin = ""; while($#args >= 2) # If the optional arguments are there. { my $argRef = string_trim(pop @args); @@ -1465,9 +1515,14 @@ sub on_wrap_any_property($) $deprecation_docs = string_unquote(string_trim($1)); } } + elsif($argRef =~ /^newin(.*)/) #If newin is at the start. + { + $newin = string_unquote(string_trim($1)); + } } - return ($filename, $line_num, $argPropertyName, $argCppType, $argDeprecated, $deprecation_docs); + return ($filename, $line_num, $argPropertyName, $argCppType, + $argDeprecated, $deprecation_docs, $newin); } sub on_wrap_property($) @@ -1477,9 +1532,11 @@ sub on_wrap_property($) return unless ($self->check_for_eof()); - my ($filename, $line_num, $argPropertyName, $argCppType, $argDeprecated, $deprecation_docs) = $self->on_wrap_any_property(); + my ($filename, $line_num, $argPropertyName, $argCppType, $argDeprecated, + $deprecation_docs, $newin) = $self->on_wrap_any_property(); - $objOutputter->output_wrap_property($filename, $line_num, $argPropertyName, $argCppType, $$self{c_class}, $argDeprecated, $deprecation_docs); + $objOutputter->output_wrap_property($filename, $line_num, $argPropertyName, + $argCppType, $$self{c_class}, $argDeprecated, $deprecation_docs, $newin); } sub on_wrap_child_property($) @@ -1489,9 +1546,11 @@ sub on_wrap_child_property($) return unless ($self->check_for_eof()); - my ($filename, $line_num, $argPropertyName, $argCppType, $argDeprecated, $deprecation_docs) = $self->on_wrap_any_property(); + my ($filename, $line_num, $argPropertyName, $argCppType, $argDeprecated, + $deprecation_docs, $newin) = $self->on_wrap_any_property(); - $objOutputter->output_wrap_child_property($filename, $line_num, $argPropertyName, $argCppType, $$self{c_class}, $argDeprecated, $deprecation_docs); + $objOutputter->output_wrap_child_property($filename, $line_num, $argPropertyName, + $argCppType, $$self{c_class}, $argDeprecated, $deprecation_docs, $newin); } sub output_wrap_check($$$$$$) @@ -1515,12 +1574,14 @@ sub output_wrap_check($$$$$$) # void output_wrap($CppDecl, $signal_name, $filename, $line_num, $bCustomDefaultHandler, # $bNoDefaultHandler, $bCustomCCallback, $bRefreturn, $ifdef, -# $commentblock, $deprecated, $deprecation_docs, $exceptionHandler) -sub output_wrap_signal($$$$$$$$$$$$) +# $commentblock, $deprecated, $deprecation_docs, $newin, $exceptionHandler, +# $detail_name, $bTwoSignalMethods) +sub output_wrap_signal($$$$$$$$$$$$$$$$$) { my ($self, $CppDecl, $signal_name, $filename, $line_num, $bCustomDefaultHandler, $bNoDefaultHandler, $bCustomCCallback, $bRefreturn, $ifdef, - $commentblock, $deprecated, $deprecation_docs, $exceptionHandler) = @_; + $commentblock, $deprecated, $deprecation_docs, $newin, $exceptionHandler, + $detail_name, $bTwoSignalMethods) = @_; #Some checks: return if ($self->output_wrap_check($CppDecl, $signal_name, @@ -1554,7 +1615,8 @@ sub output_wrap_signal($$$$$$$$$$$$) $objOutputter->output_wrap_sig_decl($filename, $line_num, $objCSignal, $objCppSignal, $signal_name, $bCustomCCallback, $ifdef, $commentblock, - $deprecated, $deprecation_docs, $exceptionHandler); + $deprecated, $deprecation_docs, $newin, $exceptionHandler, + $detail_name, $bTwoSignalMethods); if($bNoDefaultHandler eq 0) { @@ -1570,12 +1632,12 @@ sub output_wrap_signal($$$$$$$$$$$$) } # void output_wrap_vfunc($CppDecl, $vfunc_name, $filename, $line_num, -# $refreturn, $refreturn_ctype, +# $refreturn, $keep_return, $refreturn_ctype, # $custom_vfunc, $custom_vfunc_callback, $ifdef, $errthrow, # $slot_name, $slot_callback, $no_slot_copy, $returnValue, $exceptionHandler) -sub output_wrap_vfunc($$$$$$$$$$$$$$) +sub output_wrap_vfunc($$$$$$$$$$$$$$$$$) { - my ($self, $CppDecl, $vfunc_name, $filename, $line_num, $refreturn, $refreturn_ctype, + my ($self, $CppDecl, $vfunc_name, $filename, $line_num, $refreturn, $keep_return, $refreturn_ctype, $custom_vfunc, $custom_vfunc_callback, $ifdef, $errthrow, $slot_name, $slot_callback, $no_slot_copy, $returnValue, $exceptionHandler) = @_; @@ -1608,6 +1670,7 @@ sub output_wrap_vfunc($$$$$$$$$$$$$$) # These macros are defined in vfunc.m4: $$objCppVfunc{rettype_needs_ref} = $refreturn; + $$objCppVfunc{keep_return} = $keep_return; $$objCppVfunc{return_value} = $returnValue; $$objCppVfunc{exception_handler} = $exceptionHandler; $$objCppVfunc{name} .= "_vfunc"; #All vfuncs should have the "_vfunc" suffix, and a separate easily-named invoker method. |