From 90f4e9b863c9a5490c7417e0fd4ada26c7c20b28 Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Mon, 21 Oct 2024 12:51:40 -0600 Subject: [PATCH] regen/embed.pl: Handle m with p flags Prior to this commit these were illegal. This causes embed.fnc to generate macro 'Perl_foo' #defined to be macro 'foo'. If the macro name is all upper case, we instead get macro 'PERL_FOO' for 'FOO'. This could be used to easily convert existing macros into having long names should some become a name space pollution problem. This also documents in embed.fnc, under the 'm' flag discussion, how to use this instead of placing things in mathoms.c, or creating stub functions. --- autodoc.pl | 6 +++- embed.fnc | 84 +++++++++++++++++++++++++++++++++----------------- mathoms.c | 10 +++--- regen/embed.pl | 22 ++++++++----- 4 files changed, 80 insertions(+), 42 deletions(-) diff --git a/autodoc.pl b/autodoc.pl index bac73619a167..77cfe22a780b 100644 --- a/autodoc.pl +++ b/autodoc.pl @@ -1878,7 +1878,11 @@ ($fh, $section_name, $element_name, $docref) || $needs_Perl_entry || $cant_use_short_name) { - $name = "Perl_$name"; + # An all uppercase macro name gets an uppercase prefix. + my $perl = ($flags =~ /m/ && $name !~ /[[:lower:]]/) + ? "PERL_" + : "Perl_"; + $name = "$perl$name"; # We can't hide the existence of any thread context # parameter when using the "Perl_" long form. So it must diff --git a/embed.fnc b/embed.fnc index d1a291205ca6..1839d440cc63 100644 --- a/embed.fnc +++ b/embed.fnc @@ -14,7 +14,8 @@ : real (full) name, with any appropriate thread context paramaters, thus hiding : that detail from the typical code. : -: Most macros (as opposed to functions) listed here are the complete full name. +: Many macros (as opposed to functions) listed here are the complete full name, +: though we may want to start converting those to have full names. : : All non-static functions defined by perl need to be listed in this file. : embed.pl uses the entries here to construct: @@ -157,8 +158,9 @@ : and you know at a glance that the macro actually has documentation. It : doesn't by itself create any documentation; instead the other apidoc lines : pull in information specified by these lines. Many of the lines in this -: file for macros could be pulled out of here and replaced by these lines -: throughout the source. It is a goal to do that as convenience dictates. +: file for macros that don't also have the 'p' flag (described below) could be +: pulled out of here and replaced by these lines throughout the source. It is +: a goal to do that as convenience dictates. : : The other apidoc lines either have the usage data as part of the line, or : pull in the data from this file or apidoc_defn lines. @@ -210,10 +212,10 @@ : line that begins with an '='. In particular, an '=cut' line ends that : documentation without introducing something new. : -: Various macros and other elements aren't listed here in embed.fnc. They are -: documented in the same manner, but since they don't have this file to get -: information from, the defining lines have the syntax and meaning they do in -: this file, so it can be specified: +: Various macros and other elements aren't listed here in embed.fnc (though +: they could be). They are documented in the same manner, but since they don't +: have this file to get information from, the defining lines have the syntax +: and meaning they do in this file, so it can be specified: : : =for apidoc flags|return_type|name|arg1|arg2|...|argN : =for apidoc_item flags|return_type|name|arg1|arg2|...|argN @@ -301,14 +303,13 @@ : functions flagged with this, the installation can run Configure with : the -Accflags='-DNO_MATHOMS' parameter to not even compile them. : -: Sometimes the function has been subsumed by a more general one (say, -: by adding a flags parameter), and a macro exists with the original -: short name API, and it calls the new function, bypassing this one, and -: the original 'Perl_' form is being deprecated. In this case also -: specify the 'M' flag. +: If the function can be implemented as a macro (that evaluates its +: arguments exactly once), use the 'm' and 'p' flags together to implement +: this. (See the discussion under 'm'.) Another option for this is to +: use the 'M' flag. : -: Without the M flag, these functions should be deprecated, and it is an -: error to not also specify the 'D' flag. +: Without the m or M flags, these functions should be deprecated, and it +: is an error to not also specify the 'D' flag. : : The 'b' functions are normally moved to mathoms.c, but if : circumstances dictate otherwise, they can be anywhere, provided the @@ -439,24 +440,50 @@ : __attribute__always_inline__ is added : : 'm' Implemented as a macro; there is no function associated with this -: name, and hence no long Perl_ or S_ name. However, if the macro name -: itself begins with 'Perl_', autodoc.pl will show a thread context -: parameter unless the 'T' flag is specified. +: name. There is no long S_ name. +: +: However, you may #define the macro with a long name like 'Perl_foo', +: and specify the 'p' flag. This will cause an embed.h entry to be +: created that #defines 'foo' as 'Perl_foo'. This can be used to make +: any macro have a long name, perhaps to avoid name collisions. If +: instead you define the macro as 'PERL_FOO' (all uppercase), the +: embed.h entry will use all uppercase. +: +: It is particularly useful tp preserve backward compatibility when a +: function is converted to be a macro (remembering to not create a macro +: which evaluates its parameters more than once). Most of mathoms.c +: could be converted to use this facility. When there is no thread +: context involved, you just do something like +: +: #define Perl_foo(a, b, c) Perl_bar(a, b, 0, c) +: +: Otherwise consider this general case where there is a series of macros +: that build on the previous ones by calling something with a different +: name or with an extra parameter beyond what the previous one did: +: +: #define Perl_foo(mTHX, a) Perl_bar1(aTHX, a) +: #define Perl_bar1(mTHX, a) Perl_bar2(aTHX, a, 0) +: #define Perl_bar2(mTHX, a, b) Perl_bar3(aTHX, a, b, 0) +: #define Perl_bar3(mTHX, a, b, c) Perl_func(aTHX_ a, b, c, 0) +: +: Use the formal parameter name 'mTHX,' (which stands for "macro thread +: context") as the first in each macro definition, and call the next +: macro in the sequence with 'aTHX,' (Note the commas). Eventually, the +: sequence will end with a function call (or else there would be no need +: for thread context). For that instead call it with 'aTHX_' (with an +: underscore instead of a comma). : : suppress proto.h entry (actually, not suppressed, but commented out) : suppress entry in the list of exported symbols available on all : platforms -: suppress embed.h entry, as the implementation should furnish the macro +: suppress embed.h entry (when no 'p' flag), as the implementation +: should furnish the macro : : 'M' The implementation is furnishing its own macro instead of relying on : the automatically generated short name macro (which simply expands to : call the real name function). One reason to do this is if the -: parameters need to be cast from what the caller has, or if there is a -: macro that bypasses this function (whose long name is being retained -: for backward compatibility for those who call it with that name). An -: example is when a new function is created with an extra parameter and -: a wrapper macro is added that has the old API, but calls the new one -: with the exta parameter set to a default. +: parameters need to be cast from what the caller has. There is less +: need to do this now that 'm' and 'p' together is supported. : : This flag requires the 'p' flag to be specified, as there would be no : need to do this if the function weren't publicly accessible before. @@ -492,8 +519,8 @@ : : This is used for whatever reason to force the function to be called : with the long name. Perhaps there is a varargs issue. Use the 'M' -: flag instead for wrapper macros, and legacy-only functions should -: also use 'b'. +: or 'm' flags instead for wrapper macros, and legacy-only functions +: should also use 'b'. : : embed.h: suppress "#define foo Perl_foo" : @@ -518,9 +545,10 @@ : : proto.h: add __attribute__pure__ : -: 'p' Function in source code has a Perl_ prefix: +: 'p' Function or macro in source code has a Perl_ prefix: : -: proto.h: function is declared as Perl_foo rather than foo +: proto.h: function or macro is declared as Perl_foo rather than foo +: (though the entries for macros will be commented out) : embed.h: "#define foo Perl_foo" entries added : : 'R' Return value must not be ignored (also implied by 'a' and 'P' flags): diff --git a/mathoms.c b/mathoms.c index 27fa2969d1b1..b7c4760964f1 100644 --- a/mathoms.c +++ b/mathoms.c @@ -22,15 +22,15 @@ /* * This file contains mathoms, various binary artifacts from previous * versions of Perl which we cannot completely remove from the core - * code. There are two reasons functions should be here: + * code. There is only one reason these days for functions should be here: * * 1) A function has been replaced by a macro within a minor release, * so XS modules compiled against an older release will expect to * still be able to link against the function - * 2) A function Perl_foo(...) with #define foo Perl_foo(aTHX_ ...) - * has been replaced by a macro, e.g. #define foo(...) foo_flags(...,0) - * but XS code may still explicitly use the long form, i.e. - * Perl_foo(aTHX_ ...) + * + * It used to be that this was the way to handle the case were a function + * Perl_foo(...) had been replaced by a macro. But see the 'm' flag discussion + * in embed.fnc for a better way to handle this. * * This file can't just be cleaned out periodically, because that would break * builds with -DPERL_NO_SHORT_NAMES diff --git a/regen/embed.pl b/regen/embed.pl index 3cfc2a799e33..0c409204ffe3 100755 --- a/regen/embed.pl +++ b/regen/embed.pl @@ -49,7 +49,14 @@ ($$) # prefixes 'S_' or 'Perl_' my ($func, $flags) = @_; - return "Perl_$func" if $flags =~ /[ps]/; + if ($flags =~ /[ps]/) { + + # An all uppercase macro name gets an uppercase prefix. + return ($flags =~ /m/ && $flags =~ /p/ && $func !~ /[[:lower:]]/) + ? "PERL_$func" + : "Perl_$func"; + } + return "S_$func" if $flags =~ /[SIi]/; return $func; } @@ -141,10 +148,6 @@ sub generate_proto_h { if ($flags =~ /S/) { die_at_end "$plain_func: m and S flags are mutually exclusive"; } - elsif ($flags =~ /p/ && $has_context) { - die_at_end "$plain_func: m flag with p flag currently requires" - . " T flag"; - } } else { die_at_end "$plain_func: u flag only usable with m" if $flags =~ /u/; @@ -509,7 +512,7 @@ sub embed_h { my $inner_ind= $ind ? " " : " "; if ($flags !~ /[omM]/ or ($flags =~ /m/ && $flags =~ /p/)) { my $argc = scalar @$args; - if ($flags =~ /[Tm]/) { + if ($flags =~ /[T]/) { my $full_name = full_name($func, $flags); next if $full_name eq $func; # Don't output a no-op. $ret = indent_define($func, $full_name, $ind); @@ -532,8 +535,11 @@ sub embed_h { $use_va_list ? ("__VA_ARGS__") : ()); $ret = "#${ind}define $func($paramlist) "; add_indent($ret,full_name($func, $flags) . "(aTHX"); - $ret .= "_ " if $replacelist; - $ret .= $replacelist; + if ($replacelist) { + $ret .= ($flags =~ /m/) ? "," : "_ "; + $ret .= $replacelist; + } + if ($flags =~ /W/) { if ($replacelist) { $ret .= " comma_aDEPTH";