# implicit interpreter context argument.
#
+sub full_name ($$) { # Returns the function name with potentially the
+ # prefixes 'S_' or 'Perl_'
+ my ($func, $flags) = @_;
+
+ return "S_$func" if $flags =~ /[si]/;
+ return "Perl_$func" if $flags =~ /[bp]/;
+ return $func;
+}
+
sub open_print_header {
my ($file, $quote) = @_;
my ($embed, $core, $ext, $api) = setup_embed();
-# walk table providing an array of components in each line to
-# subroutine, printing the result
-sub walk_table (&@) {
- my ($function, $filename) = @_;
- my $F;
- if (ref $filename) { # filehandle
- $F = $filename;
- }
- else {
- $F = open_print_header($filename);
- }
- foreach (@$embed) {
- my @outs = &{$function}(@$_);
- # $function->(@args) is not 5.003
- print $F @outs;
- }
- unless (ref $filename) {
- read_only_bottom_close_and_rename($F);
- }
-}
-
# generate proto.h
{
my $pr = open_print_header("proto.h");
my @names_of_nn;
my $func;
+ if (! $can_ignore && $retval eq 'void') {
+ warn "It is nonsensical to require the return value of a void function ($plain_func) to be checked";
+ }
+
+ my $scope_type_flag_count = 0;
+ $scope_type_flag_count++ if $flags =~ /s/;
+ $scope_type_flag_count++ if $flags =~ /i/;
+ $scope_type_flag_count++ if $flags =~ /p/;
+ warn "$plain_func: i, p, and s flags are all mutually exclusive"
+ if $scope_type_flag_count > 1;
my $splint_flags = "";
if ( $SPLINT && !$commented_out ) {
$splint_flags .= '/*@noreturn@*/ ' if $never_returns;
}
if ($flags =~ /([si])/) {
- my $type = ($1 eq 's') ? "STATIC" : "PERL_STATIC_INLINE";
- warn "$func: i and s flags are mutually exclusive"
- if $flags =~ /s/ && $flags =~ /i/;
+ my $type;
+ if ($never_returns) {
+ $type = $1 eq 's' ? "PERL_STATIC_NO_RET" : "PERL_STATIC_INLINE_NO_RET";
+ }
+ else {
+ $type = $1 eq 's' ? "STATIC" : "PERL_STATIC_INLINE";
+ }
$retval = "$type $splint_flags$retval";
- $func = "S_$plain_func";
}
else {
- $retval = "PERL_CALLCONV $splint_flags$retval";
- if ($flags =~ /[bp]/) {
- $func = "Perl_$plain_func";
- } else {
- $func = $plain_func;
+ if ($never_returns) {
+ $retval = "PERL_CALLCONV_NO_RET $splint_flags$retval";
+ }
+ else {
+ $retval = "PERL_CALLCONV $splint_flags$retval";
}
}
+ $func = full_name($plain_func, $flags);
$ret = "$retval\t$func(";
if ( $has_context ) {
$ret .= @args ? "pTHX_ " : "pTHX";
}
if( $flags =~ /f/ ) {
my $prefix = $has_context ? 'pTHX_' : '';
- my $args = scalar @args;
- my $pat = $args - 1;
- my $macro = @nonnull && $nonnull[-1] == $pat
+ my ($args, $pat);
+ if ($args[-1] eq '...') {
+ $args = scalar @args;
+ $pat = $args - 1;
+ $args = $prefix . $args;
+ }
+ else {
+ # don't check args, and guess which arg is the pattern
+ # (one of 'fmt', 'pat', 'f'),
+ $args = 0;
+ my @fmts = grep $args[$_] =~ /\b(f|pat|fmt)$/, 0..$#args;
+ if (@fmts != 1) {
+ die "embed.pl: '$plain_func': can't determine pattern arg\n";
+ }
+ $pat = $fmts[0] + 1;
+ }
+ my $macro = grep($_ == $pat, @nonnull)
? '__attribute__format__'
: '__attribute__format__null_ok__';
- push @attrs, sprintf "%s(__printf__,%s%d,%s%d)", $macro,
- $prefix, $pat, $prefix, $args;
- }
- if ( @nonnull ) {
- my @pos = map { $has_context ? "pTHX_$_" : $_ } @nonnull;
- push @attrs, map { sprintf( "__attribute__nonnull__(%s)", $_ ) } @pos;
+ if ($plain_func =~ /strftime/) {
+ push @attrs, sprintf "%s(__strftime__,%s1,0)", $macro, $prefix;
+ }
+ else {
+ push @attrs, sprintf "%s(__printf__,%s%d,%s)", $macro,
+ $prefix, $pat, $args;
+ }
}
if ( @attrs ) {
$ret .= "\n";
unless ($flags =~ /[om]/) {
my $args = scalar @args;
if ($flags =~ /n/) {
- if ($flags =~ /s/) {
- $ret = hide($func,"S_$func");
- }
- elsif ($flags =~ /p/) {
- $ret = hide($func,"Perl_$func");
- }
+ $ret = hide($func, full_name($func, $flags));
}
elsif ($args and $args[$args-1] =~ /\.\.\./) {
if ($flags =~ /p/) {
# we're out of luck for varargs functions under CPP
# So we can only do these macros for no implicit context:
$ret = "#ifndef PERL_IMPLICIT_CONTEXT\n"
- . hide($func,"Perl_$func") . "#endif\n";
+ . hide($func, full_name($func, $flags)) . "#endif\n";
}
}
else {
$ret = "#define $func($alist)";
my $t = int(length($ret) / 8);
$ret .= "\t" x ($t < 4 ? 4 - $t : 1);
- if ($flags =~ /[si]/) {
- $ret .= "S_$func(aTHX";
- }
- elsif ($flags =~ /p/) {
- $ret .= "Perl_$func(aTHX";
- }
+ $ret .= full_name($func, $flags) . "(aTHX";
$ret .= "_ " if $alist;
$ret .= $alist . ")\n";
}
# define perl_atexit(a,b) call_atexit(a,b)
END
-walk_table {
- my ($flags,$retval,$func,@args) = @_;
- return unless $func;
- return unless $flags =~ /O/;
+foreach (@$embed) {
+ my ($flags, $retval, $func, @args) = @$_;
+ next unless $func;
+ next unless $flags =~ /O/;
my $alist = join ",", @az[0..$#args];
my $ret = "# define perl_$func($alist)";
my $t = (length $ret) >> 3;
$ret .= "\t" x ($t < 5 ? 5 - $t : 1);
- "$ret$func($alist)\n";
-} $em;
+ print $em "$ret$func($alist)\n";
+}
my @nocontext;
{
my $sym;
for $sym (@intrp) {
+ if ($sym eq 'sawampersand') {
+ print $em "#ifndef PL_sawampersand\n";
+ }
print $em multon($sym,'I','vTHX->');
+ if ($sym eq 'sawampersand') {
+ print $em "#endif\n";
+ }
}
print $em <<'END';