mirror of
https://github.com/Perl/perl5.git
synced 2026-01-26 08:38:23 +00:00
h2ph: define all symbols at runtime
Preprocessor directives must be processed strictly in order. `#if` and
`#ifdef` directives can inspect the current state of defined symbols.
That's why it is wrong to translate `#define FOO() ...` to `sub foo() {
... }` since subroutine definitions are processed unconditionally at
compile time, before the rest of the code starts running.
In particular,
unless(defined(&FOO)) {
sub FOO () { eval q(1); }
}
is equivalent to
# at compile time:
sub FOO () { eval q(1); }
# ... later, at runtime:
unless(defined(&FOO)) {
# does nothing
}
Fix this case by always wrapping subroutines in eval '...', which moves
the symbol definition to runtime, regardless of what $t (our indentation
state) is.
Similarly, generate `_h2ph_pre.ph` without the functionally useless
`unless (defined &...) { }` blocks. We don't need runtime definitions
(via eval) here because nothing in this file depends on the dynamic
state of macro definitions. It's all `#define`s, no `#if`s.
Fixes #22109.
This commit is contained in:
parent
bcd28b1883
commit
f38f760a11
@ -16,6 +16,15 @@
|
||||
#define ERROR(x) fprintf(stderr, "%s\n", x[2][3][0])
|
||||
#endif /* ERROR */
|
||||
|
||||
/* check for correct order of definitions vs. conditionals */
|
||||
#ifdef NOT_DEFINED_HERE()
|
||||
/* handle indented directives */
|
||||
#error "NOT_DEFINED_HERE should not be defined at this point!"
|
||||
#endif
|
||||
|
||||
/* function-like macro with no parameters, outside of any conditional */
|
||||
#define NOT_DEFINED_HERE() 42
|
||||
|
||||
#ifndef _H2PH_H_
|
||||
#define _H2PH_H_
|
||||
|
||||
|
||||
@ -2,18 +2,22 @@ require '_h2ph_pre.ph';
|
||||
|
||||
no warnings qw(redefine misc);
|
||||
|
||||
unless(defined(&SQUARE)) {
|
||||
sub SQUARE {
|
||||
my($x) = @_;
|
||||
eval 'sub SQUARE {
|
||||
my($x) = @_;
|
||||
eval q((($x)*($x)));
|
||||
}
|
||||
}
|
||||
}' unless defined(&SQUARE);
|
||||
unless(defined(&ERROR)) {
|
||||
eval 'sub ERROR {
|
||||
my($x) = @_;
|
||||
eval q( &fprintf( &stderr, \\"%s\\\\n\\", $x->[2][3][0]));
|
||||
}' unless defined(&ERROR);
|
||||
}
|
||||
if(defined(&NOT_DEFINED_HERE)) {
|
||||
die("NOT_DEFINED_HERE should not be defined at this point!");
|
||||
}
|
||||
eval 'sub NOT_DEFINED_HERE () {
|
||||
eval q(42);
|
||||
}' unless defined(&NOT_DEFINED_HERE);
|
||||
unless(defined(&_H2PH_H_)) {
|
||||
eval 'sub _H2PH_H_ () {1;}' unless defined(&_H2PH_H_);
|
||||
# "$Revision h2ph.h,v 1.0 98/05/04 20:42:14 billy $"
|
||||
|
||||
@ -392,7 +392,6 @@ sub EMIT {
|
||||
|
||||
$new = reindent($new);
|
||||
$args = reindent($args);
|
||||
if ($t ne '') {
|
||||
$new =~ s/(['\\])/\\$1/g; #']);
|
||||
if ($opt_h) {
|
||||
print OUT $t,
|
||||
@ -402,9 +401,6 @@ sub EMIT {
|
||||
print OUT $t,
|
||||
"eval 'sub $name $proto\{\n$t ${args}eval q($new);\n$t}' unless defined(\&$name);\n";
|
||||
}
|
||||
} else {
|
||||
print OUT "unless(defined(\&$name)) {\n sub $name $proto\{\n\t${args}eval q($new);\n }\n}\n";
|
||||
}
|
||||
%curargs = ();
|
||||
return;
|
||||
}
|
||||
@ -774,7 +770,7 @@ sub inc_dirs
|
||||
sub build_preamble_if_necessary
|
||||
{
|
||||
# Increment $VERSION every time this function is modified:
|
||||
my $VERSION = 4;
|
||||
my $VERSION = 5;
|
||||
my $preamble = "$Dest_dir/_h2ph_pre.ph";
|
||||
|
||||
# Can we skip building the preamble file?
|
||||
@ -812,18 +808,16 @@ sub build_preamble_if_necessary
|
||||
my $def = $define{$_};
|
||||
$def =~ s/$arg/\$\{$arg\}/g;
|
||||
print PREAMBLE <<DEFINE;
|
||||
unless (defined &$macro) { sub $macro(\$) { my (\$$arg) = \@_; \"$def\" } }
|
||||
sub $macro(\$) { my (\$$arg) = \@_; \"$def\" }
|
||||
|
||||
DEFINE
|
||||
} elsif
|
||||
($define{$_} =~ /^([+-]?(\d+)?\.\d+([eE][+-]?\d+)?)[FL]?$/) {
|
||||
# float:
|
||||
print PREAMBLE
|
||||
"unless (defined &$_) { sub $_() { $1 } }\n\n";
|
||||
print PREAMBLE "sub $_() { $1 }\n\n";
|
||||
} elsif ($define{$_} =~ /^([+-]?\d+)U?L{0,2}$/i) {
|
||||
# integer:
|
||||
print PREAMBLE
|
||||
"unless (defined &$_) { sub $_() { $1 } }\n\n";
|
||||
print PREAMBLE "sub $_() { $1 }\n\n";
|
||||
} elsif ($define{$_} =~ /^([+-]?0x[\da-f]+)U?L{0,2}$/i) {
|
||||
# hex integer
|
||||
# Special cased, since perl warns on hex integers
|
||||
@ -834,21 +828,16 @@ DEFINE
|
||||
# platform-specific definition.
|
||||
my $code = $1;
|
||||
$code = "hex('$code')" if length $code > 10;
|
||||
print PREAMBLE
|
||||
"unless (defined &$_) { sub $_() { $code } }\n\n";
|
||||
print PREAMBLE "sub $_() { $code }\n\n";
|
||||
} elsif ($define{$_} =~ /^\w+$/) {
|
||||
my $def = $define{$_};
|
||||
if ($isatype{$def}) {
|
||||
print PREAMBLE
|
||||
"unless (defined &$_) { sub $_() { \"$def\" } }\n\n";
|
||||
print PREAMBLE "sub $_() { \"$def\" }\n\n";
|
||||
} else {
|
||||
print PREAMBLE
|
||||
"unless (defined &$_) { sub $_() { &$def } }\n\n";
|
||||
print PREAMBLE "sub $_() { &$def }\n\n";
|
||||
}
|
||||
} else {
|
||||
print PREAMBLE
|
||||
"unless (defined &$_) { sub $_() { \"",
|
||||
quotemeta($define{$_}), "\" } }\n\n";
|
||||
print PREAMBLE "sub $_() { \"\Q$define{$_}\E\" }\n\n";
|
||||
}
|
||||
}
|
||||
print PREAMBLE "\n1;\n"; # avoid 'did not return a true value' when empty
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user