Patch: Put local($^I, @ARGV) = ... trick back into perlfaq5
[p5sagit/p5-mst-13.2.git] / embed.pl
index 5ade24a..fee2363 100755 (executable)
--- a/embed.pl
+++ b/embed.pl
-#!/usr/bin/perl
+#!/usr/bin/perl -w
 
-open(EM, ">embed.h") || die "Can't create embed.h: $!\n";
+require 5.003; # keep this compatible, an old perl is all we may have before
+                # we build the new one
+
+#
+# See database of global and static function prototypes in embed.fnc
+# This is used to generate prototype headers under various configurations,
+# export symbols lists for different platforms, and macros to provide an
+# implicit interpreter context argument.
+#
+
+open IN, "embed.fnc" or die $!;
+
+# walk table providing an array of components in each line to
+# subroutine, printing the result
+sub walk_table (&@) {
+    my $function = shift;
+    my $filename = shift || '-';
+    my $leader = shift;
+    my $trailer = shift;
+    my $F;
+    local *F;
+    if (ref $filename) {       # filehandle
+       $F = $filename;
+    }
+    else {
+       unlink $filename;
+       open F, ">$filename" or die "Can't open $filename: $!";
+       $F = \*F;
+    }
+    print $F $leader if $leader;
+    seek IN, 0, 0;             # so we may restart
+    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; # $function->(@args) is not 5.003
+    }
+    print $F $trailer if $trailer;
+    close $F unless ref $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 (<>) {
+#      if (/^#\s*include\s+"perl.h"/) {
+#          my $file = uc $ARGV;
+#          $file =~ s/\./_/g;
+#          print "#define PERL_IN_$file\n";
+#      }
+#      s{^(\w+)\s*\(}
+#       {
+#          my $f = $1;
+#          my $repl = "$f(";
+#          if (exists $functions->{$f}) {
+#              my $flags = $functions->{$f}[0];
+#              $repl = "Perl_$repl" if $flags =~ /p/;
+#              unless ($flags =~ /n/) {
+#                  $repl .= "pTHX";
+#                  $repl .= "_ " if @{$functions->{$f}} > 3;
+#              }
+#              warn("$ARGV:$.:$repl\n");
+#          }
+#          $repl;
+#       }e;
+       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;      # restart $.
+    }
+    exit;
+}
+
+#munge_c_files();
+
+# generate proto.h
+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;
+}
+
+# generates global.sym (API export list), and populates %global with global symbols
+sub write_global_sym {
+    my $ret = "";
+    if (@_ > 1) {
+       my ($flags,$retval,$func,@args) = @_;
+       if ($flags =~ /A/ && $flags !~ /[xm]/) { # public API, so export
+           $func = "Perl_$func" if $flags =~ /p/;
+           $ret = "$func\n";
+       }
+    }
+    $ret;
+}
+
+
+walk_table(\&write_protos, 'proto.h', <<'EOT');
+/*
+ *    proto.h
+ *
+ *    Copyright (c) 1997-2002, Larry Wall
+ *
+ *    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 autogenerated from data in embed.pl.  Edit that file
+ * and run 'make regen_headers' to effect changes.
+ */
+
+EOT
+
+walk_table(\&write_global_sym, 'global.sym', <<'EOT');
+#
+#    global.sym
+#
+#    Copyright (c) 1997-2002, Larry Wall
+#
+#    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 autogenerated from data in embed.pl.  Edit that file
+# and run 'make regen_headers' to effect changes.
+#
+
+EOT
+
+# XXX others that may need adding
+#       warnhook
+#       hints
+#       copline
+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]*#.*//;          # Delete comments.
+       if (/^\s*(\S+)\s*$/) {
+           my $sym = $1;
+           warn "duplicate symbol $sym while processing $file\n"
+               if exists $$syms{$sym};
+           $$syms{$sym} = 1;
+       }
+    }
+    close(FILE);
+}
+
+# Perl_pp_* and Perl_ck_* are in pp.sym
+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]*#.*//;          # Delete comments.
+       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");
+}
+
+unlink 'embed.h';
+open(EM, '> embed.h') or die "Can't create embed.h: $!\n";
 
 print EM <<'END';
-/* !!!!!!!   DO NOT EDIT THIS FILE   !!!!!!! 
-   This file is built by embed.pl from global.sym and interp.sym.
-   Any changes made here will be lost 
-*/
+/*
+ *    embed.h
+ *
+ *    Copyright (c) 1997-2002, Larry Wall
+ *
+ *    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.pl, pp.sym, intrpvar.h,
+ *  perlvars.h and thrdvar.h.  Any changes made here will be lost!
+ */
 
 /* (Doing namespace management portably in C is really gross.) */
 
-/*  EMBED has no run-time penalty, but helps keep the Perl namespace
-    from colliding with that used by other libraries pulled in
-    by extensions or by embedding perl.  Allow a cc -DNO_EMBED
-    override, however, to keep binary compatability with previous
-    versions of perl.
-*/
-#ifndef NO_EMBED
-#  define EMBED 1 
+/* NO_EMBED is no longer supported. i.e. EMBED is always active. */
+
+/* Hide global symbols */
+
+#if !defined(PERL_IMPLICIT_CONTEXT)
+
+END
+
+walk_table {
+    my $ret = "";
+    if (@_ == 1) {
+       my $arg = shift;
+       $ret .= "$arg\n" if $arg =~ /^#\s*(if|ifn?def|else|endif)\b/;
+    }
+    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");
+           }
+       }
+    }
+    $ret;
+} \*EM;
+
+for $sym (sort keys %ppsym) {
+    $sym =~ s/^Perl_//;
+    print EM hide($sym, "Perl_$sym");
+}
+
+print EM <<'END';
+
+#else  /* PERL_IMPLICIT_CONTEXT */
+
+END
+
+my @az = ('a'..'z');
+
+walk_table {
+    my $ret = "";
+    if (@_ == 1) {
+       my $arg = shift;
+       $ret .= "$arg\n" if $arg =~ /^#\s*(if|ifn?def|else|endif)\b/;
+    }
+    else {
+       my ($flags,$retval,$func,@args) = @_;
+       unless ($flags =~ /[om]/) {
+           my $args = scalar @args;
+           if ($args and $args[$args-1] =~ /\.\.\./) {
+               # we're out of luck for varargs functions under CPP
+           }
+           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";
+           }
+       }
+    }
+    $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';
+
+#endif /* PERL_IMPLICIT_CONTEXT */
+
+END
+
+print EM <<'END';
+
+/* Compatibility stubs.  Compile extensions with -DPERL_NOCOMPAT to
+   disable them.
+ */
+
+#if !defined(PERL_CORE)
+#  define sv_setptrobj(rv,ptr,name)    sv_setref_iv(rv,name,PTR2IV(ptr))
+#  define sv_setptrref(rv,ptr)         sv_setref_iv(rv,Nullch,PTR2IV(ptr))
+#endif
+
+#if !defined(PERL_CORE) && !defined(PERL_NOCOMPAT)
+
+/* 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.
+ */
+#  define perl_atexit(a,b)             call_atexit(a,b)
+#  define perl_call_argv(a,b,c)                call_argv(a,b,c)
+#  define perl_call_pv(a,b)            call_pv(a,b)
+#  define perl_call_method(a,b)                call_method(a,b)
+#  define perl_call_sv(a,b)            call_sv(a,b)
+#  define perl_eval_sv(a,b)            eval_sv(a,b)
+#  define perl_eval_pv(a,b)            eval_pv(a,b)
+#  define perl_require_pv(a)           require_pv(a)
+#  define perl_get_sv(a,b)             get_sv(a,b)
+#  define perl_get_av(a,b)             get_av(a,b)
+#  define perl_get_hv(a,b)             get_hv(a,b)
+#  define perl_get_cv(a,b)             get_cv(a,b)
+#  define perl_init_i18nl10n(a)                init_i18nl10n(a)
+#  define perl_init_i18nl14n(a)                init_i18nl14n(a)
+#  define perl_new_ctype(a)            new_ctype(a)
+#  define perl_new_collate(a)          new_collate(a)
+#  define perl_new_numeric(a)          new_numeric(a)
+
+/* 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.
+ */
+#if defined(PERL_IMPLICIT_CONTEXT)
+#  define croak                                Perl_croak_nocontext
+#  define deb                          Perl_deb_nocontext
+#  define die                          Perl_die_nocontext
+#  define form                         Perl_form_nocontext
+#  define load_module                  Perl_load_module_nocontext
+#  define mess                         Perl_mess_nocontext
+#  define newSVpvf                     Perl_newSVpvf_nocontext
+#  define sv_catpvf                    Perl_sv_catpvf_nocontext
+#  define sv_setpvf                    Perl_sv_setpvf_nocontext
+#  define warn                         Perl_warn_nocontext
+#  define warner                       Perl_warner_nocontext
+#  define sv_catpvf_mg                 Perl_sv_catpvf_mg_nocontext
+#  define sv_setpvf_mg                 Perl_sv_setpvf_mg_nocontext
 #endif
 
-#ifdef EMBED
+#endif /* !defined(PERL_CORE) && !defined(PERL_NOCOMPAT) */
+
+#if !defined(PERL_IMPLICIT_CONTEXT)
+/* undefined symbols, point them back at the usual ones */
+#  define Perl_croak_nocontext         Perl_croak
+#  define Perl_die_nocontext           Perl_die
+#  define Perl_deb_nocontext           Perl_deb
+#  define Perl_form_nocontext          Perl_form
+#  define Perl_load_module_nocontext   Perl_load_module
+#  define Perl_mess_nocontext          Perl_mess
+#  define Perl_newSVpvf_nocontext      Perl_newSVpvf
+#  define Perl_sv_catpvf_nocontext     Perl_sv_catpvf
+#  define Perl_sv_setpvf_nocontext     Perl_sv_setpvf
+#  define Perl_warn_nocontext          Perl_warn
+#  define Perl_warner_nocontext                Perl_warner
+#  define Perl_sv_catpvf_mg_nocontext  Perl_sv_catpvf_mg
+#  define Perl_sv_setpvf_mg_nocontext  Perl_sv_setpvf_mg
+#endif
 
-/* globals we need to hide from the world */
 END
 
-open(GL, "<global.sym") || die "Can't open global.sym: $!\n";
+close(EM);
 
-while(<GL>) {
-       s/[ \t]*#.*//;          # Delete comments.
-       next unless /\S/;
-       s/^\s*(\S+).*$/#define $1\t\tPerl_$1/;
-       $global{$1} = 1; 
-       s/(................\t)\t/$1/;
-       print EM $_;
+unlink 'embedvar.h';
+open(EM, '> embedvar.h')
+    or die "Can't create embedvar.h: $!\n";
+
+print EM <<'END';
+/*
+ *    embedvar.h
+ *
+ *    Copyright (c) 1997-2002, Larry Wall
+ *
+ *    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.pl, pp.sym, intrpvar.h,
+ *  perlvars.h and thrdvar.h.  Any changes made here will be lost!
+ */
+
+/* (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   # supported for compatibility
+     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.
+
+   #3, #4, #5, and #6 are supported directly, while #2 is a special
+   case of #3 (supported by redefining vTHX appropriately).
+*/
+
+#if defined(MULTIPLICITY)
+/* cases 2, 3 and 5 above */
+
+#  if defined(PERL_IMPLICIT_CONTEXT)
+#    define vTHX       aTHX
+#  else
+#    define vTHX       PERL_GET_INTERP
+#  endif
+
+END
+
+for $sym (sort keys %thread) {
+    print EM multon($sym,'T','vTHX->');
+}
+
+print EM <<'END';
+
+#  if defined(USE_5005THREADS)
+/* case 5 above */
+
+END
+
+for $sym (sort keys %intrp) {
+    print EM multon($sym,'I','PERL_GET_INTERP->');
 }
 
-close(GL) || warn "Can't close global.sym: $!\n";
+print EM <<'END';
+
+#  else                /* !USE_5005THREADS */
+/* cases 2 and 3 above */
+
+END
+
+for $sym (sort keys %intrp) {
+    print EM multon($sym,'I','vTHX->');
+}
 
 print EM <<'END';
 
-#endif /* EMBED */
+#  endif       /* USE_5005THREADS */
+
+#else  /* !MULTIPLICITY */
+
+/* cases 1 and 4 above */
 
-/* Put interpreter specific symbols into a struct? */
+END
 
-#ifdef MULTIPLICITY
+for $sym (sort keys %intrp) {
+    print EM multoff($sym,'I');
+}
 
-/* Undefine symbols that were defined by EMBED. Somewhat ugly */
+print EM <<'END';
+
+#  if defined(USE_5005THREADS)
+/* case 4 above */
 
 END
 
+for $sym (sort keys %thread) {
+    print EM multon($sym,'T','aTHX->');
+}
 
-open(INT, "<interp.sym") || die "Can't open interp.sym: $!\n";
-while (<INT>) {
-       s/[ \t]*#.*//;          # Delete comments.
-       next unless /\S/;
-       s/^\s*(\S*).*$/#undef $1/;
-       print EM $_ if (exists $global{$1});
+print EM <<'END';
+
+#  else        /* !USE_5005THREADS */
+/* case 1 above */
+
+END
+
+for $sym (sort keys %thread) {
+    print EM multoff($sym,'T');
 }
-close(INT) || warn "Can't close interp.sym: $!\n";
 
-print EM "\n";
+print EM <<'END';
 
-open(INT, "<interp.sym") || die "Can't open interp.sym: $!\n";
-while (<INT>) {
-       s/[ \t]*#.*//;          # Delete comments.
-       next unless /\S/;
-       s/^\s*(\S+).*$/#define $1\t\t(curinterp->I$1)/;
-       s/(................\t)\t/$1/;
-       print EM $_;
+#  endif       /* USE_5005THREADS */
+#endif /* MULTIPLICITY */
+
+#if defined(PERL_GLOBAL_STRUCT)
+
+END
+
+for $sym (sort keys %globvar) {
+    print EM multon($sym,'G','PL_Vars.');
 }
-close(INT) || warn "Can't close interp.sym: $!\n";
 
 print EM <<'END';
 
-#else  /* not multiple, so translate interpreter symbols the other way... */
+#else /* !PERL_GLOBAL_STRUCT */
 
 END
 
-open(INT, "<interp.sym") || die "Can't open interp.sym: $!\n";
-while (<INT>) {
-       s/[ \t]*#.*//;          # Delete comments.
-       next unless /\S/;
-       s/^\s*(\S+).*$/#define I$1\t\t$1/;
-       s/(................\t)\t/$1/;
-       print EM $_;
+for $sym (sort keys %globvar) {
+    print EM multoff($sym,'G');
 }
-close(INT) || warn "Can't close interp.sym: $!\n";
 
 print EM <<'END';
 
-#endif /* MULTIPLICITY */
+#endif /* PERL_GLOBAL_STRUCT */
+
+#ifdef PERL_POLLUTE            /* disabled by default in 5.6.0 */
+
 END
 
+for $sym (sort @extvars) {
+    print EM hide($sym,"PL_$sym");
+}
+
+print EM <<'END';
+
+#endif /* PERL_POLLUTE */
+END
+
+close(EM);
+
+unlink 'perlapi.h';
+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 <<'EOT';
+/*
+ *    perlapi.h
+ *
+ *    Copyright (c) 1997-2002, Larry Wall
+ *
+ *    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.pl, pp.sym, intrpvar.h,
+ *  perlvars.h and thrdvar.h.  Any changes made here will be lost!
+ */
+
+/* declare accessor functions for Perl variables */
+#ifndef __perlapi_h__
+#define __perlapi_h__
+
+#if defined (MULTIPLICITY)
+
+START_EXTERN_C
+
+#undef PERLVAR
+#undef PERLVARA
+#undef PERLVARI
+#undef PERLVARIC
+#define PERLVAR(v,t)   EXTERN_C t* Perl_##v##_ptr(pTHX);
+#define PERLVARA(v,n,t)        typedef t PL_##v##_t[n];                        \
+                       EXTERN_C PL_##v##_t* Perl_##v##_ptr(pTHX);
+#define PERLVARI(v,t,i)        PERLVAR(v,t)
+#define PERLVARIC(v,t,i) PERLVAR(v, const t)
+
+#include "thrdvar.h"
+#include "intrpvar.h"
+#include "perlvars.h"
+
+#undef PERLVAR
+#undef PERLVARA
+#undef PERLVARI
+#undef PERLVARIC
+
+END_EXTERN_C
+
+#if defined(PERL_CORE)
+
+/* 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;
+
+print CAPI <<'EOT';
+/*
+ *    perlapi.c
+ *
+ *    Copyright (c) 1997-2002, Larry Wall
+ *
+ *    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.pl, pp.sym, intrpvar.h,
+ *  perlvars.h and thrdvar.h.  Any changes made here will be lost!
+ */
+
+#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);
+
+# 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
+);