test.pl tweaks from Rafael and Pudge (assuming I deciphered
[p5sagit/p5-mst-13.2.git] / utils / h2xs.PL
index 2b36af0..b856d89 100644 (file)
@@ -143,6 +143,11 @@ Turn on debugging messages.
 Allows an extension to be created for a header even if that header is
 not found in standard include directories.
 
+=item B<-g>, B<--global>
+
+Include code for safely storing static data in the .xs file. 
+Extensions that do no make use of static data can ignore this option.
+
 =item B<-h>, B<-?>, B<--help>
 
 Print the usage, help and version for this h2xs and exit.
@@ -465,6 +470,7 @@ OPTIONS:
     -d, --debugging       Turn on debugging messages.
     -f, --force           Force creation of the extension even if the C header
                           does not exist.
+    -g, --global          Include code for safely storing static data in the .xs file. 
     -h, -?, --help        Display this help message
     -k, --omit-const-func Omit 'const' attribute on function arguments
                           (used with -x).
@@ -498,6 +504,7 @@ my ($opt_A,
     $opt_c,
     $opt_d,
     $opt_f,
+    $opt_g,
     $opt_h,
     $opt_k,
     $opt_m,
@@ -528,6 +535,7 @@ my %options = (
                 'omit-constant|c'    => \$opt_c,
                 'debugging|d'        => \$opt_d,
                 'force|f'            => \$opt_f,
+                'global|g'           => \$opt_g,
                 'help|h|?'           => \$opt_h,
                 'omit-const-func|k'  => \$opt_k,
                 'gen-tied-var|m'     => \$opt_m,
@@ -810,6 +818,139 @@ my %vdecl_hash;
 my @vdecls;
 
 if( ! $opt_X ){  # use XS, unless it was disabled
+  open(COMPAT, ">compat.h") || die "Can't create $ext$modpname/compat.h: $!\n";
+  warn "Writing $ext$modpname/compat.h\n";
+  print COMPAT <<EOM, <<'EOM';
+/* WARNING: This file has been autogenerated by h2xs $H2XS_VERSION */
+
+EOM
+
+
+#ifndef PERL_VERSION
+
+#    include "patchlevel.h"
+#    define PERL_REVISION      5
+#    define PERL_VERSION       PATCHLEVEL
+#    define PERL_SUBVERSION    SUBVERSION
+
+#endif /* PERL_VERSION */
+
+
+
+/* 
+ * This file is taken from perl.h  & modified slightly to make it backward 
+ * comapable with older versions of Perl.
+ * 
+ */
+
+#if PERL_REVISION == 5 && \
+    (PERL_VERSION < 7 || (PERL_VERSION == 7 && PERL_SUBVERSION < 2 ))
+
+/*
+ * Boilerplate macros for initializing and accessing interpreter-local
+ * data from C.  All statics in extensions should be reworked to use
+ * this, if you want to make the extension thread-safe.  See ext/re/re.xs
+ * for an example of the use of these macros.
+ *
+ * Code that uses these macros is responsible for the following:
+ * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
+ * 2. Declare a typedef named my_cxt_t that is a structure that contains
+ *    all the data that needs to be interpreter-local.
+ * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
+ * 4. Use the MY_CXT_INIT macro such that it is called exactly once
+ *    (typically put in the BOOT: section).
+ * 5. Use the members of the my_cxt_t structure everywhere as
+ *    MY_CXT.member.
+ * 6. Use the dMY_CXT macro (a declaration) in all the functions that
+ *    access MY_CXT.
+ */
+
+#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
+    defined(PERL_CAPI)    || defined(PERL_IMPLICIT_CONTEXT)
+
+/* This must appear in all extensions that define a my_cxt_t structure,
+ * right after the definition (i.e. at file scope).  The non-threads
+ * case below uses it to declare the data as static. */
+#define START_MY_CXT
+
+#if PERL_REVISION == 5 && \
+    (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION < 68 ))
+/* Fetches the SV that keeps the per-interpreter data. */
+#define dMY_CXT_SV \
+       SV *my_cxt_sv = perl_get_sv(MY_CXT_KEY, FALSE)
+#else /* >= perl5.004_68 */
+#define dMY_CXT_SV \
+       SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY,             \
+                                 sizeof(MY_CXT_KEY)-1, TRUE)
+#endif /* < perl5.004_68 */
+
+/* This declaration should be used within all functions that use the
+ * interpreter-local data. */
+#define dMY_CXT        \
+       dMY_CXT_SV;                                                     \
+       my_cxt_t *my_cxtp = (my_cxt_t*)SvUV(my_cxt_sv)
+
+/* Creates and zeroes the per-interpreter data.
+ * (We allocate my_cxtp in a Perl SV so that it will be released when
+ * the interpreter goes away.) */
+#define MY_CXT_INIT \
+       dMY_CXT_SV;                                                     \
+       /* newSV() allocates one more than needed */                    \
+       my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
+       Zero(my_cxtp, 1, my_cxt_t);                                     \
+       sv_setuv(my_cxt_sv, (UV)my_cxtp)
+
+/* This macro must be used to access members of the my_cxt_t structure.
+ * e.g. MYCXT.some_data */
+#define MY_CXT         (*my_cxtp)
+
+/* Judicious use of these macros can reduce the number of times dMY_CXT
+ * is used.  Use is similar to pTHX, aTHX etc. */
+#define pMY_CXT                my_cxt_t *my_cxtp
+#define pMY_CXT_       pMY_CXT,
+#define _pMY_CXT       ,pMY_CXT
+#define aMY_CXT                my_cxtp
+#define aMY_CXT_       aMY_CXT,
+#define _aMY_CXT       ,aMY_CXT
+
+#else /* single interpreter */
+
+#ifndef NOOP
+#  define NOOP (void)0
+#endif
+
+#ifdef HASATTRIBUTE
+#  define PERL_UNUSED_DECL __attribute__((unused))
+#else
+#  define PERL_UNUSED_DECL
+#endif    
+
+#ifndef dNOOP
+#  define dNOOP extern int Perl___notused PERL_UNUSED_DECL
+#endif
+
+#define START_MY_CXT   static my_cxt_t my_cxt;
+#define dMY_CXT_SV     dNOOP
+#define dMY_CXT                dNOOP
+#define MY_CXT_INIT    NOOP
+#define MY_CXT         my_cxt
+
+#define pMY_CXT                void
+#define pMY_CXT_
+#define _pMY_CXT
+#define aMY_CXT
+#define aMY_CXT_
+#define _aMY_CXT
+
+#endif 
+
+#endif /* perl < 5.7.2 */
+
+/* End of file compat.h */
+
+EOM
+  close COMPAT ;
+
   open(XS, ">$modfname.xs") || die "Can't create $ext$modpname/$modfname.xs: $!\n";
   if ($opt_x) {
     require Config;            # Run-time directive
@@ -1189,6 +1330,7 @@ print XS <<"END";
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
+#include "compat.h"
 
 END
 if( @path_h ){
@@ -1201,6 +1343,21 @@ if( @path_h ){
     print XS "\n";
 }
 
+print XS <<"END" if $opt_g;
+
+/* Global Data */
+
+#define MY_CXT_KEY "${module}::_guts" XS_VERSION
+
+typedef struct {
+    /* Put Global Data in here */
+    int dummy;         /* you can access this elsewhere as MY_CXT.dummy */
+} my_cxt_t;
+
+START_MY_CXT
+
+END
+
 my %pointer_typedefs;
 my %struct_typedefs;
 
@@ -1270,6 +1427,18 @@ END
 # XS declaration:
 print XS "INCLUDE: $constsfname.xs\n" unless $opt_c;
 
+print XS <<"END" if $opt_g;
+
+BOOT:
+{
+    MY_CXT_INIT;
+    /* If any of the fields in the my_cxt_t struct need
+       to be initialised, do it here.
+     */
+}
+
+END
+
 foreach (sort keys %const_xsub) {
     print XS <<"END";
 char *