require 5.003;
BEGIN {
require 'regen_lib.pl';
}
sub do_not_edit ($)
{
my $file = shift;
my $years;
if ($file eq 'embed.h') {
$years = '1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003';
} elsif ($file eq 'embedvar.h') {
$years = '1999, 2000, 2001, 2002, 2003';
} elsif ($file eq 'global.sym') {
$years = '1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003';
} elsif ($file eq 'perlapi.c') {
$years = '1999, 2000, 2001';
} elsif ($file eq 'perlapi.h') {
$years = '1999, 2000, 2001, 2002, 2003';
} elsif ($file eq 'proto.h') {
$years = '1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003';
}
$years =~ s/1999,/1999,\n / if length $years > 40;
my $warning = <<EOW;
$file
Copyright (C) $years, by Larry Wall and others
You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the README file.
!!!!!!! DO NOT EDIT THIS FILE !!!!!!!
This file is built by embed.pl from data in embed.fnc, embed.pl,
pp.sym, intrpvar.h, perlvars.h and thrdvar.h.
Any changes made here will be lost!
Edit those files and run 'make regen_headers' to effect changes.
EOW
if ($file =~ m:\.[ch]$:) {
$warning =~ s:^: * :gm;
$warning =~ s: +$::gm;
$warning =~ s: :/:;
$warning =~ s:$:/:;
}
else {
$warning =~ s:^: $warning =~ s: +$::gm;
}
$warning;
}
open IN, "embed.fnc" or die $!;
sub walk_table (&@) {
my $function = shift;
my $filename = shift || '-';
my $leader = shift;
defined $leader or $leader = do_not_edit ($filename);
my $trailer = shift;
my $F;
local *F;
if (ref $filename) { $F = $filename;
}
else {
safer_unlink $filename;
open F, ">$filename" or die "Can't open $filename: $!";
$F = \*F;
}
print $F $leader if $leader;
seek IN, 0, 0; while (<IN>) {
chomp;
next if /^:/;
while (s|\\$||) {
$_ .= <IN>;
chomp;
}
my @args;
if (/^\s*( @args = $_;
}
else {
@args = split /\s*\|\s*/, $_;
}
my @outs = &{$function}(@args);
print $F @outs; }
print $F $trailer if $trailer;
unless (ref $filename) {
close $F or die "Error closing $filename: $!";
}
}
sub munge_c_files () {
my $functions = {};
unless (@ARGV) {
warn "\@ARGV empty, nothing to do\n";
return;
}
walk_table {
if (@_ > 1) {
$functions->{$_[2]} = \@_ if $_[@_-1] =~ /\.\.\./;
}
} '/dev/null', '';
local $^I = '.bak';
while (<>) {
s{(\b(\w+)[ \t]*\([ \t]*(?!aTHX))}
{
my $repl = $1;
my $f = $2;
if (exists $functions->{$f}) {
$repl .= "aTHX_ ";
warn("$ARGV:$.:$`#$repl#$'");
}
$repl;
}eg;
print;
close ARGV if eof; }
exit;
}
my $wrote_protected = 0;
sub write_protos {
my $ret = "";
if (@_ == 1) {
my $arg = shift;
$ret .= "$arg\n";
}
else {
my ($flags,$retval,$func,@args) = @_;
$ret .= '/* ' if $flags =~ /m/;
if ($flags =~ /s/) {
$retval = "STATIC $retval";
$func = "S_$func";
}
else {
$retval = "PERL_CALLCONV $retval";
if ($flags =~ /p/) {
$func = "Perl_$func";
}
}
$ret .= "$retval\t$func(";
unless ($flags =~ /n/) {
$ret .= "pTHX";
$ret .= "_ " if @args;
}
if (@args) {
$ret .= join ", ", @args;
}
else {
$ret .= "void" if $flags =~ /n/;
}
$ret .= ")";
$ret .= " __attribute__((noreturn))" if $flags =~ /r/;
if( $flags =~ /f/ ) {
my $prefix = $flags =~ /n/ ? '' : 'pTHX_';
my $args = scalar @args;
$ret .= "\n#ifdef CHECK_FORMAT\n";
$ret .= sprintf " __attribute__((format(__printf__,%s%d,%s%d)))",
$prefix, $args - 1, $prefix, $args;
$ret .= "\n#endif\n";
}
$ret .= ";";
$ret .= ' */' if $flags =~ /m/;
$ret .= "\n";
}
$ret;
}
sub write_global_sym {
my $ret = "";
if (@_ > 1) {
my ($flags,$retval,$func,@args) = @_;
if ($flags =~ /[AX]/ && $flags !~ /[xm]/
|| $flags =~ /b/) { $func = "Perl_$func" if $flags =~ /[pbX]/;
$ret = "$func\n";
}
}
$ret;
}
walk_table(\&write_protos, "proto.h", undef);
walk_table(\&write_global_sym, "global.sym", undef);
my @extvars = qw(sv_undef sv_yes sv_no na dowarn
curcop compiling
tainting tainted stack_base stack_sp sv_arenaroot
no_modify
curstash DBsub DBsingle debstash
rsfp
stdingv
defgv
errgv
rsfp_filters
perldb
diehook
dirty
perl_destruct_level
ppaddr
);
sub readsyms (\%$) {
my ($syms, $file) = @_;
local (*FILE, $_);
open(FILE, "< $file")
or die "embed.pl: Can't open $file: $!\n";
while (<FILE>) {
s/[ \t]* if (/^\s*(\S+)\s*$/) {
my $sym = $1;
warn "duplicate symbol $sym while processing $file\n"
if exists $$syms{$sym};
$$syms{$sym} = 1;
}
}
close(FILE);
}
readsyms my %ppsym, 'pp.sym';
sub readvars(\%$$@) {
my ($syms, $file,$pre,$keep_pre) = @_;
local (*FILE, $_);
open(FILE, "< $file")
or die "embed.pl: Can't open $file: $!\n";
while (<FILE>) {
s/[ \t]* if (/PERLVARA?I?C?\($pre(\w+)/) {
my $sym = $1;
$sym = $pre . $sym if $keep_pre;
warn "duplicate symbol $sym while processing $file\n"
if exists $$syms{$sym};
$$syms{$sym} = $pre || 1;
}
}
close(FILE);
}
my %intrp;
my %thread;
readvars %intrp, 'intrpvar.h','I';
readvars %thread, 'thrdvar.h','T';
readvars %globvar, 'perlvars.h','G';
my $sym;
foreach $sym (sort keys %thread) {
warn "$sym in intrpvar.h as well as thrdvar.h\n" if exists $intrp{$sym};
}
sub undefine ($) {
my ($sym) = @_;
"#undef $sym\n";
}
sub hide ($$) {
my ($from, $to) = @_;
my $t = int(length($from) / 8);
"#define $from" . "\t" x ($t < 3 ? 3 - $t : 1) . "$to\n";
}
sub bincompat_var ($$) {
my ($pfx, $sym) = @_;
my $arg = ($pfx eq 'G' ? 'NULL' : 'aTHX');
undefine("PL_$sym") . hide("PL_$sym", "(*Perl_${pfx}${sym}_ptr($arg))");
}
sub multon ($$$) {
my ($sym,$pre,$ptr) = @_;
hide("PL_$sym", "($ptr$pre$sym)");
}
sub multoff ($$) {
my ($sym,$pre) = @_;
return hide("PL_$pre$sym", "PL_$sym");
}
safer_unlink 'embed.h';
open(EM, '> embed.h') or die "Can't create embed.h: $!\n";
print EM do_not_edit ("embed.h"), <<'END';
/* (Doing namespace management portably in C is really gross.) */
/* By defining PERL_NO_SHORT_NAMES (not done by default) the short forms
* (like warn instead of Perl_warn) for the API are not defined.
* Not defining the short forms is a good thing for cleaner embedding. */
/* Hide global symbols */
END
walk_table {
my $ret = "";
if (@_ == 1) {
my $arg = shift;
$ret .= "$arg\n" if $arg =~ /^ }
else {
my ($flags,$retval,$func,@args) = @_;
unless ($flags =~ /[om]/) {
if ($flags =~ /s/) {
$ret .= hide($func,"S_$func");
}
elsif ($flags =~ /p/) {
$ret .= hide($func,"Perl_$func");
}
}
if ($ret ne '' && $flags !~ /A/) {
if ($flags =~ /E/) {
$ret = "#if defined(PERL_CORE) || defined(PERL_EXT)\n$ret#endif\n";
} else {
$ret = "#ifdef PERL_CORE\n$ret#endif\n";
}
}
}
$ret;
} \*EM, "";
for $sym (sort keys %ppsym) {
$sym =~ s/^Perl_//;
print EM hide($sym, "Perl_$sym");
}
print EM <<'END';
END
my @az = ('a'..'z');
walk_table {
my $ret = "";
if (@_ == 1) {
my $arg = shift;
$ret .= "$arg\n" if $arg =~ /^ }
else {
my ($flags,$retval,$func,@args) = @_;
unless ($flags =~ /[om]/) {
my $args = scalar @args;
if ($args and $args[$args-1] =~ /\.\.\./) {
}
elsif ($flags =~ /n/) {
if ($flags =~ /s/) {
$ret .= hide($func,"S_$func");
}
elsif ($flags =~ /p/) {
$ret .= hide($func,"Perl_$func");
}
}
else {
my $alist = join(",", @az[0..$args-1]);
$ret = "#define $func($alist)";
my $t = int(length($ret) / 8);
$ret .= "\t" x ($t < 4 ? 4 - $t : 1);
if ($flags =~ /s/) {
$ret .= "S_$func(aTHX";
}
elsif ($flags =~ /p/) {
$ret .= "Perl_$func(aTHX";
}
$ret .= "_ " if $alist;
$ret .= $alist . ")\n";
}
}
unless ($flags =~ /A/) {
if ($flags =~ /E/) {
$ret = "#if defined(PERL_CORE) || defined(PERL_EXT)\n$ret#endif\n";
} else {
$ret = "#ifdef PERL_CORE\n$ret#endif\n";
}
}
}
$ret;
} \*EM, "";
for $sym (sort keys %ppsym) {
$sym =~ s/^Perl_//;
if ($sym =~ /^ck_/) {
print EM hide("$sym(a)", "Perl_$sym(aTHX_ a)");
}
elsif ($sym =~ /^pp_/) {
print EM hide("$sym()", "Perl_$sym(aTHX)");
}
else {
warn "Illegal symbol '$sym' in pp.sym";
}
}
print EM <<'END';
END
print EM <<'END';
/* Compatibility stubs. Compile extensions with -DPERL_NOCOMPAT to
disable them.
*/
/* Compatibility for various misnamed functions. All functions
in the API that begin with "perl_" (not "Perl_") take an explicit
interpreter context pointer.
The following are not like that, but since they had a "perl_"
prefix in previous versions, we provide compatibility macros.
*/
/* varargs functions can't be handled with CPP macros. :-(
This provides a set of compatibility functions that don't take
an extra argument but grab the context pointer using the macro
dTHX.
*/
/* undefined symbols, point them back at the usual ones */
END
close(EM) or die "Error closing EM: $!";
safer_unlink 'embedvar.h';
open(EM, '> embedvar.h')
or die "Can't create embedvar.h: $!\n";
print EM do_not_edit ("embedvar.h"), <<'END';
/* (Doing namespace management portably in C is really gross.) */
/*
The following combinations of MULTIPLICITY, USE_5005THREADS
and PERL_IMPLICIT_CONTEXT are supported:
1) none
2) MULTIPLICITY 3) MULTIPLICITY && PERL_IMPLICIT_CONTEXT
4) USE_5005THREADS && PERL_IMPLICIT_CONTEXT
5) MULTIPLICITY && USE_5005THREADS && PERL_IMPLICIT_CONTEXT
All other combinations of these flags are errors.
case of */
/* cases 2, 3 and 5 above */
END
for $sym (sort keys %thread) {
print EM multon($sym,'T','vTHX->');
}
print EM <<'END';
/* case 5 above */
END
for $sym (sort keys %intrp) {
print EM multon($sym,'I','PERL_GET_INTERP->');
}
print EM <<'END';
/* cases 2 and 3 above */
END
for $sym (sort keys %intrp) {
print EM multon($sym,'I','vTHX->');
}
print EM <<'END';
/* cases 1 and 4 above */
END
for $sym (sort keys %intrp) {
print EM multoff($sym,'I');
}
print EM <<'END';
/* case 4 above */
END
for $sym (sort keys %thread) {
print EM multon($sym,'T','aTHX->');
}
print EM <<'END';
/* case 1 above */
END
for $sym (sort keys %thread) {
print EM multoff($sym,'T');
}
print EM <<'END';
END
for $sym (sort keys %globvar) {
print EM multon($sym,'G','PL_Vars.');
}
print EM <<'END';
END
for $sym (sort keys %globvar) {
print EM multoff($sym,'G');
}
print EM <<'END';
END
for $sym (sort @extvars) {
print EM hide($sym,"PL_$sym");
}
print EM <<'END';
END
close(EM) or die "Error closing EM: $!";
safer_unlink 'perlapi.h';
safer_unlink 'perlapi.c';
open(CAPI, '> perlapi.c') or die "Can't create perlapi.c: $!\n";
open(CAPIH, '> perlapi.h') or die "Can't create perlapi.h: $!\n";
print CAPIH do_not_edit ("perlapi.h"), <<'EOT';
/* declare accessor functions for Perl variables */
START_EXTERN_C
EXTERN_C PL_
END_EXTERN_C
/* accessor functions for Perl variables (provide binary compatibility) */
/* these need to be mentioned here, or most linkers won't put them in
the perl executable */
#ifndef PERL_NO_FORCE_LINK
START_EXTERN_C
#ifndef DOINIT
EXT void *PL_force_link_funcs[];
#else
EXT void *PL_force_link_funcs[] = {
#undef PERLVAR
#undef PERLVARA
#undef PERLVARI
#undef PERLVARIC
#define PERLVAR(v,t) (void*)Perl_##v##_ptr,
#define PERLVARA(v,n,t) PERLVAR(v,t)
#define PERLVARI(v,t,i) PERLVAR(v,t)
#define PERLVARIC(v,t,i) PERLVAR(v,t)
#include "thrdvar.h"
#include "intrpvar.h"
#include "perlvars.h"
#undef PERLVAR
#undef PERLVARA
#undef PERLVARI
#undef PERLVARIC
};
#endif /* DOINIT */
END_EXTERN_C
#endif /* PERL_NO_FORCE_LINK */
#else /* !PERL_CORE */
EOT
foreach $sym (sort keys %intrp) {
print CAPIH bincompat_var('I',$sym);
}
foreach $sym (sort keys %thread) {
print CAPIH bincompat_var('T',$sym);
}
foreach $sym (sort keys %globvar) {
print CAPIH bincompat_var('G',$sym);
}
print CAPIH <<'EOT';
#endif /* !PERL_CORE */
#endif /* MULTIPLICITY */
#endif /* __perlapi_h__ */
EOT
close CAPIH or die "Error closing CAPIH: $!";
print CAPI do_not_edit ("perlapi.c"), <<'EOT';
#include "EXTERN.h"
#include "perl.h"
#include "perlapi.h"
#if defined (MULTIPLICITY)
/* accessor functions for Perl variables (provides binary compatibility) */
START_EXTERN_C
#undef PERLVAR
#undef PERLVARA
#undef PERLVARI
#undef PERLVARIC
#define PERLVAR(v,t) t* Perl_##v##_ptr(pTHX) \
{ return &(aTHX->v); }
#define PERLVARA(v,n,t) PL_##v##_t* Perl_##v##_ptr(pTHX) \
{ return &(aTHX->v); }
#define PERLVARI(v,t,i) PERLVAR(v,t)
#define PERLVARIC(v,t,i) PERLVAR(v, const t)
#include "thrdvar.h"
#include "intrpvar.h"
#undef PERLVAR
#undef PERLVARA
#define PERLVAR(v,t) t* Perl_##v##_ptr(pTHX) \
{ return &(PL_##v); }
#define PERLVARA(v,n,t) PL_##v##_t* Perl_##v##_ptr(pTHX) \
{ return &(PL_##v); }
#undef PERLVARIC
#define PERLVARIC(v,t,i) const t* Perl_##v##_ptr(pTHX) \
{ return (const t *)&(PL_##v); }
#include "perlvars.h"
#undef PERLVAR
#undef PERLVARA
#undef PERLVARI
#undef PERLVARIC
END_EXTERN_C
#endif /* MULTIPLICITY */
EOT
close(CAPI) or die "Error closing CAPI: $!";
# functions that take va_list* for implementing vararg functions
# NOTE: makedef.pl must be updated if you add symbols to %vfuncs
# XXX %vfuncs currently unused
my %vfuncs = qw(
Perl_croak Perl_vcroak
Perl_warn Perl_vwarn
Perl_warner Perl_vwarner
Perl_die Perl_vdie
Perl_form Perl_vform
Perl_load_module Perl_vload_module
Perl_mess Perl_vmess
Perl_deb Perl_vdeb
Perl_newSVpvf Perl_vnewSVpvf
Perl_sv_setpvf Perl_sv_vsetpvf
Perl_sv_setpvf_mg Perl_sv_vsetpvf_mg
Perl_sv_catpvf Perl_sv_vcatpvf
Perl_sv_catpvf_mg Perl_sv_vcatpvf_mg
Perl_dump_indent Perl_dump_vindent
Perl_default_protect Perl_vdefault_protect
);