1N/Apackage Devel::PPPort;
1N/A
1N/A=head1 NAME
1N/A
1N/ADevel::PPPort - Perl/Pollution/Portability
1N/A
1N/A=head1 SYNOPSIS
1N/A
1N/A Devel::PPPort::WriteFile() ; # defaults to ./ppport.h
1N/A Devel::PPPort::WriteFile('someheader.h') ;
1N/A
1N/A=head1 DESCRIPTION
1N/A
1N/APerl has changed over time, gaining new features, new functions,
1N/Aincreasing its flexibility, and reducing the impact on the C namespace
1N/Aenvironment (reduced pollution). The header file, typicaly C<ppport.h>,
1N/Awritten by this module attempts to bring some of the newer Perl
1N/Afeatures to older versions of Perl, so that you can worry less about
1N/Akeeping track of old releases, but users can still reap the benefit.
1N/A
1N/AWhy you should use C<ppport.h> in modern code: so that your code will work
1N/Awith the widest range of Perl interpreters possible, without significant
1N/Aadditional work.
1N/A
1N/AWhy you should attempt older code to fully use C<ppport.h>: because
1N/Athe reduced pollution of newer Perl versions is an important thing, so
1N/Aimportant that the old polluting ways of original Perl modules will not be
1N/Asupported very far into the future, and your module will almost certainly
1N/Abreak! By adapting to it now, you'll gained compatibility and a sense of
1N/Ahaving done the electronic ecology some good.
1N/A
1N/AHow to use ppport.h: Don't direct the user to download C<Devel::PPPort>,
1N/Aand don't make C<ppport.h> optional. Rather, just take the most recent
1N/Acopy of C<ppport.h> that you can find (probably in C<Devel::PPPort>
1N/Aon CPAN), copy it into your project, adjust your project to use it,
1N/Aand distribute the header along with your module.
1N/A
1N/AC<Devel::PPPort> contains a single function, called C<WriteFile>. It's
1N/Apurpose is to write a 'C' header file that is used when writing XS
1N/Amodules. The file contains a series of macros that allow XS modules to
1N/Abe built using older versions of Perl.
1N/A
1N/AThis module is used by h2xs to write the file F<ppport.h>.
1N/A
1N/A=head2 WriteFile
1N/A
1N/AC<WriteFile> takes a zero or one parameters. When called with one
1N/Aparameter it expects to be passed a filename. When called with no
1N/Aparameters, it defults to the filename C<./pport.h>.
1N/A
1N/AThe function returns TRUE if the file was written successfully. Otherwise
1N/Ait returns FALSE.
1N/A
1N/A=head1 ppport.h
1N/A
1N/AThe file written by this module, typically C<ppport.h>, provides access
1N/Ato the following Perl API if not already available (and in some cases [*]
1N/Aeven if available, access to a fixed interface):
1N/A
1N/A aMY_CXT
1N/A aMY_CXT_
1N/A _aMY_CXT
1N/A aTHX
1N/A aTHX_
1N/A AvFILLp
1N/A boolSV(b)
1N/A call_argv
1N/A call_method
1N/A call_pv
1N/A call_sv
1N/A dAX
1N/A DEFSV
1N/A dITEMS
1N/A dMY_CXT
1N/A dMY_CXT_SV
1N/A dNOOP
1N/A dTHR
1N/A dTHX
1N/A dTHXa
1N/A dTHXoa
1N/A ERRSV
1N/A get_av
1N/A get_cv
1N/A get_hv
1N/A get_sv
1N/A grok_hex
1N/A grok_oct
1N/A grok_bin
1N/A grok_number
1N/A grok_numeric_radix
1N/A gv_stashpvn(str,len,flags)
1N/A INT2PTR(type,int)
1N/A IVdf
1N/A MY_CXT
1N/A MY_CXT_INIT
1N/A newCONSTSUB(stash,name,sv)
1N/A newRV_inc(sv)
1N/A newRV_noinc(sv)
1N/A newSVpvn(data,len)
1N/A NOOP
1N/A NV
1N/A NVef
1N/A NVff
1N/A NVgf
1N/A PERL_REVISION
1N/A PERL_SUBVERSION
1N/A PERL_UNUSED_DECL
1N/A PERL_VERSION
1N/A PL_compiling
1N/A PL_copline
1N/A PL_curcop
1N/A PL_curstash
1N/A PL_defgv
1N/A PL_dirty
1N/A PL_hints
1N/A PL_na
1N/A PL_perldb
1N/A PL_rsfp_filters
1N/A PL_rsfpv
1N/A PL_stdingv
1N/A PL_Sv
1N/A PL_sv_no
1N/A PL_sv_undef
1N/A PL_sv_yes
1N/A pMY_CXT
1N/A pMY_CXT_
1N/A _pMY_CXT
1N/A pTHX
1N/A pTHX_
1N/A PTR2IV(ptr)
1N/A PTR2NV(ptr)
1N/A PTR2ul(ptr)
1N/A PTR2UV(ptr)
1N/A SAVE_DEFSV
1N/A START_MY_CXT
1N/A SvPVbyte(sv,lp) [*]
1N/A UVof
1N/A UVSIZE
1N/A UVuf
1N/A UVxf
1N/A UVXf
1N/A
1N/A=head1 AUTHOR
1N/A
1N/AVersion 1.x of Devel::PPPort was written by Kenneth Albanowski.
1N/A
1N/AVersion 2.x was ported to the Perl core by Paul Marquess.
1N/A
1N/A=head1 SEE ALSO
1N/A
1N/ASee L<h2xs>.
1N/A
1N/A=cut
1N/A
1N/A
1N/Apackage Devel::PPPort;
1N/A
1N/Arequire Exporter;
1N/Arequire DynaLoader;
1N/A#use warnings;
1N/Ause strict;
1N/Ause vars qw( $VERSION @ISA @EXPORT @EXPORT_OK $data );
1N/A
1N/A$VERSION = "2.011";
1N/A
1N/A@ISA = qw(Exporter DynaLoader);
1N/A@EXPORT = qw();
1N/A# Other items we are prepared to export if requested
1N/A@EXPORT_OK = qw( );
1N/A
1N/Abootstrap Devel::PPPort;
1N/A
1N/Apackage Devel::PPPort;
1N/A
1N/A{
1N/A local $/ = undef;
1N/A $data = <DATA> ;
1N/A my $now = localtime;
1N/A my $pkg = __PACKAGE__;
1N/A $data =~ s/__VERSION__/$VERSION/g;
1N/A $data =~ s/__DATE__/$now/g;
1N/A $data =~ s/__PKG__/$pkg/g;
1N/A}
1N/A
1N/Asub WriteFile
1N/A{
1N/A my $file = shift || 'ppport.h' ;
1N/A
1N/A open F, ">$file" || return undef ;
1N/A print F $data ;
1N/A close F;
1N/A
1N/A return 1 ;
1N/A}
1N/A
1N/A1;
1N/A
1N/A__DATA__;
1N/A
1N/A/* ppport.h -- Perl/Pollution/Portability Version __VERSION__
1N/A *
1N/A * Automatically Created by __PKG__ on __DATE__
1N/A *
1N/A * Do NOT edit this file directly! -- Edit PPPort.pm instead.
1N/A *
1N/A * Version 2.x, Copyright (C) 2001, Paul Marquess.
1N/A * Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
1N/A * This code may be used and distributed under the same license as any
1N/A * version of Perl.
1N/A *
1N/A * This version of ppport.h is designed to support operation with Perl
1N/A * installations back to 5.004, and has been tested up to 5.8.1.
1N/A *
1N/A * If this version of ppport.h is failing during the compilation of this
1N/A * module, please check if a newer version of Devel::PPPort is available
1N/A * on CPAN before sending a bug report.
1N/A *
1N/A * If you are using the latest version of Devel::PPPort and it is failing
1N/A * during compilation of this module, please send a report to perlbug@perl.com
1N/A *
1N/A * Include all following information:
1N/A *
1N/A * 1. The complete output from running "perl -V"
1N/A *
1N/A * 2. This file.
1N/A *
1N/A * 3. The name & version of the module you were trying to build.
1N/A *
1N/A * 4. A full log of the build that failed.
1N/A *
1N/A * 5. Any other information that you think could be relevant.
1N/A *
1N/A *
1N/A * For the latest version of this code, please retreive the Devel::PPPort
1N/A * module from CPAN.
1N/A *
1N/A */
1N/A
1N/A/*
1N/A * In order for a Perl extension module to be as portable as possible
1N/A * across differing versions of Perl itself, certain steps need to be taken.
1N/A * Including this header is the first major one, then using dTHR is all the
1N/A * appropriate places and using a PL_ prefix to refer to global Perl
1N/A * variables is the second.
1N/A *
1N/A */
1N/A
1N/A
1N/A/* If you use one of a few functions that were not present in earlier
1N/A * versions of Perl, please add a define before the inclusion of ppport.h
1N/A * for a static include, or use the GLOBAL request in a single module to
1N/A * produce a global definition that can be referenced from the other
1N/A * modules.
1N/A *
1N/A * Function: Static define: Extern define:
1N/A * newCONSTSUB() NEED_newCONSTSUB NEED_newCONSTSUB_GLOBAL
1N/A *
1N/A */
1N/A
1N/A
1N/A/* To verify whether ppport.h is needed for your module, and whether any
1N/A * special defines should be used, ppport.h can be run through Perl to check
1N/A * your source code. Simply say:
1N/A *
1N/A * perl -x ppport.h *.c *.h *.xs foo/bar*.c [etc]
1N/A *
1N/A * The result will be a list of patches suggesting changes that should at
1N/A * least be acceptable, if not necessarily the most efficient solution, or a
1N/A * fix for all possible problems. It won't catch where dTHR is needed, and
1N/A * doesn't attempt to account for global macro or function definitions,
1N/A * nested includes, typemaps, etc.
1N/A *
1N/A * In order to test for the need of dTHR, please try your module under a
1N/A * recent version of Perl that has threading compiled-in.
1N/A *
1N/A */
1N/A
1N/A
1N/A/*
1N/A#!/usr/bin/perl
1N/A@ARGV = ("*.xs") if !@ARGV;
1N/A%badmacros = %funcs = %macros = (); $replace = 0;
1N/Aforeach (<DATA>) {
1N/A $funcs{$1} = 1 if /Provide:\s+(\S+)/;
1N/A $macros{$1} = 1 if /^#\s*define\s+([a-zA-Z0-9_]+)/;
1N/A $replace = $1 if /Replace:\s+(\d+)/;
1N/A $badmacros{$2}=$1 if $replace and /^#\s*define\s+([a-zA-Z0-9_]+).*?\s+([a-zA-Z0-9_]+)/;
1N/A $badmacros{$1}=$2 if /Replace (\S+) with (\S+)/;
1N/A}
1N/Aforeach $filename (map(glob($_),@ARGV)) {
1N/A unless (open(IN, "<$filename")) {
1N/A warn "Unable to read from $file: $!\n";
1N/A next;
1N/A }
1N/A print "Scanning $filename...\n";
1N/A $c = ""; while (<IN>) { $c .= $_; } close(IN);
1N/A $need_include = 0; %add_func = (); $changes = 0;
1N/A $has_include = ($c =~ /#.*include.*ppport/m);
1N/A
1N/A foreach $func (keys %funcs) {
1N/A if ($c =~ /#.*define.*\bNEED_$func(_GLOBAL)?\b/m) {
1N/A if ($c !~ /\b$func\b/m) {
1N/A print "If $func isn't needed, you don't need to request it.\n" if
1N/A $changes += ($c =~ s/^.*#.*define.*\bNEED_$func\b.*\n//m);
1N/A } else {
1N/A print "Uses $func\n";
1N/A $need_include = 1;
1N/A }
1N/A } else {
1N/A if ($c =~ /\b$func\b/m) {
1N/A $add_func{$func} =1 ;
1N/A print "Uses $func\n";
1N/A $need_include = 1;
1N/A }
1N/A }
1N/A }
1N/A
1N/A if (not $need_include) {
1N/A foreach $macro (keys %macros) {
1N/A if ($c =~ /\b$macro\b/m) {
1N/A print "Uses $macro\n";
1N/A $need_include = 1;
1N/A }
1N/A }
1N/A }
1N/A
1N/A foreach $badmacro (keys %badmacros) {
1N/A if ($c =~ /\b$badmacro\b/m) {
1N/A $changes += ($c =~ s/\b$badmacro\b/$badmacros{$badmacro}/gm);
1N/A print "Uses $badmacros{$badmacro} (instead of $badmacro)\n";
1N/A $need_include = 1;
1N/A }
1N/A }
1N/A
1N/A if (scalar(keys %add_func) or $need_include != $has_include) {
1N/A if (!$has_include) {
1N/A $inc = join('',map("#define NEED_$_\n", sort keys %add_func)).
1N/A "#include \"ppport.h\"\n";
1N/A $c = "$inc$c" unless $c =~ s/#.*include.*XSUB.*\n/$&$inc/m;
1N/A } elsif (keys %add_func) {
1N/A $inc = join('',map("#define NEED_$_\n", sort keys %add_func));
1N/A $c = "$inc$c" unless $c =~ s/^.*#.*include.*ppport.*$/$inc$&/m;
1N/A }
1N/A if (!$need_include) {
1N/A print "Doesn't seem to need ppport.h.\n";
1N/A $c =~ s/^.*#.*include.*ppport.*\n//m;
1N/A }
1N/A $changes++;
1N/A }
1N/A
1N/A if ($changes) {
1N/A open(OUT,">/tmp/ppport.h.$$");
1N/A print OUT $c;
1N/A close(OUT);
1N/A open(DIFF, "diff -u $filename /tmp/ppport.h.$$|");
1N/A while (<DIFF>) { s!/tmp/ppport\.h\.$$!$filename.patched!; print STDOUT; }
1N/A close(DIFF);
1N/A unlink("/tmp/ppport.h.$$");
1N/A } else {
1N/A print "Looks OK\n";
1N/A }
1N/A}
1N/A__DATA__
1N/A*/
1N/A
1N/A#ifndef _P_P_PORTABILITY_H_
1N/A#define _P_P_PORTABILITY_H_
1N/A
1N/A#ifndef PERL_REVISION
1N/A# ifndef __PATCHLEVEL_H_INCLUDED__
1N/A# define PERL_PATCHLEVEL_H_IMPLICIT
1N/A# include <patchlevel.h>
1N/A# endif
1N/A# if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL)))
1N/A# include <could_not_find_Perl_patchlevel.h>
1N/A# endif
1N/A# ifndef PERL_REVISION
1N/A# define PERL_REVISION (5)
1N/A /* Replace: 1 */
1N/A# define PERL_VERSION PATCHLEVEL
1N/A# define PERL_SUBVERSION SUBVERSION
1N/A /* Replace PERL_PATCHLEVEL with PERL_VERSION */
1N/A /* Replace: 0 */
1N/A# endif
1N/A#endif
1N/A
1N/A#define PERL_BCDVERSION ((PERL_REVISION * 0x1000000L) + (PERL_VERSION * 0x1000L) + PERL_SUBVERSION)
1N/A
1N/A/* It is very unlikely that anyone will try to use this with Perl 6
1N/A (or greater), but who knows.
1N/A */
1N/A#if PERL_REVISION != 5
1N/A# error ppport.h only works with Perl version 5
1N/A#endif /* PERL_REVISION != 5 */
1N/A
1N/A#ifndef ERRSV
1N/A# define ERRSV perl_get_sv("@",FALSE)
1N/A#endif
1N/A
1N/A#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5))
1N/A/* Replace: 1 */
1N/A# define PL_Sv Sv
1N/A# define PL_compiling compiling
1N/A# define PL_copline copline
1N/A# define PL_curcop curcop
1N/A# define PL_curstash curstash
1N/A# define PL_defgv defgv
1N/A# define PL_dirty dirty
1N/A# define PL_dowarn dowarn
1N/A# define PL_hints hints
1N/A# define PL_na na
1N/A# define PL_perldb perldb
1N/A# define PL_rsfp_filters rsfp_filters
1N/A# define PL_rsfpv rsfp
1N/A# define PL_stdingv stdingv
1N/A# define PL_sv_no sv_no
1N/A# define PL_sv_undef sv_undef
1N/A# define PL_sv_yes sv_yes
1N/A/* Replace: 0 */
1N/A#endif
1N/A
1N/A#ifdef HASATTRIBUTE
1N/A# if (defined(__GNUC__) && defined(__cplusplus)) || defined(__INTEL_COMPILER)
1N/A# define PERL_UNUSED_DECL
1N/A# else
1N/A# define PERL_UNUSED_DECL __attribute__((unused))
1N/A# endif
1N/A#else
1N/A# define PERL_UNUSED_DECL
1N/A#endif
1N/A
1N/A#ifndef dNOOP
1N/A# define NOOP (void)0
1N/A# define dNOOP extern int Perl___notused PERL_UNUSED_DECL
1N/A#endif
1N/A
1N/A#ifndef dTHR
1N/A# define dTHR dNOOP
1N/A#endif
1N/A
1N/A#ifndef dTHX
1N/A# define dTHX dNOOP
1N/A# define dTHXa(x) dNOOP
1N/A# define dTHXoa(x) dNOOP
1N/A#endif
1N/A
1N/A#ifndef pTHX
1N/A# define pTHX void
1N/A# define pTHX_
1N/A# define aTHX
1N/A# define aTHX_
1N/A#endif
1N/A
1N/A#ifndef dAX
1N/A# define dAX I32 ax = MARK - PL_stack_base + 1
1N/A#endif
1N/A#ifndef dITEMS
1N/A# define dITEMS I32 items = SP - MARK
1N/A#endif
1N/A
1N/A/* IV could also be a quad (say, a long long), but Perls
1N/A * capable of those should have IVSIZE already. */
1N/A#if !defined(IVSIZE) && defined(LONGSIZE)
1N/A# define IVSIZE LONGSIZE
1N/A#endif
1N/A#ifndef IVSIZE
1N/A# define IVSIZE 4 /* A bold guess, but the best we can make. */
1N/A#endif
1N/A
1N/A#ifndef UVSIZE
1N/A# define UVSIZE IVSIZE
1N/A#endif
1N/A
1N/A#ifndef NVTYPE
1N/A# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE)
1N/A# define NVTYPE long double
1N/A# else
1N/A# define NVTYPE double
1N/A# endif
1N/Atypedef NVTYPE NV;
1N/A#endif
1N/A
1N/A#ifndef INT2PTR
1N/A
1N/A#if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE)
1N/A# define PTRV UV
1N/A# define INT2PTR(any,d) (any)(d)
1N/A#else
1N/A# if PTRSIZE == LONGSIZE
1N/A# define PTRV unsigned long
1N/A# else
1N/A# define PTRV unsigned
1N/A# endif
1N/A# define INT2PTR(any,d) (any)(PTRV)(d)
1N/A#endif
1N/A#define NUM2PTR(any,d) (any)(PTRV)(d)
1N/A#define PTR2IV(p) INT2PTR(IV,p)
1N/A#define PTR2UV(p) INT2PTR(UV,p)
1N/A#define PTR2NV(p) NUM2PTR(NV,p)
1N/A#if PTRSIZE == LONGSIZE
1N/A# define PTR2ul(p) (unsigned long)(p)
1N/A#else
1N/A# define PTR2ul(p) INT2PTR(unsigned long,p)
1N/A#endif
1N/A
1N/A#endif /* !INT2PTR */
1N/A
1N/A#ifndef boolSV
1N/A# define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no)
1N/A#endif
1N/A
1N/A#ifndef gv_stashpvn
1N/A# define gv_stashpvn(str,len,flags) gv_stashpv(str,flags)
1N/A#endif
1N/A
1N/A#ifndef newSVpvn
1N/A# define newSVpvn(data,len) ((len) ? newSVpv ((data), (len)) : newSVpv ("", 0))
1N/A#endif
1N/A
1N/A#ifndef newRV_inc
1N/A/* Replace: 1 */
1N/A# define newRV_inc(sv) newRV(sv)
1N/A/* Replace: 0 */
1N/A#endif
1N/A
1N/A/* DEFSV appears first in 5.004_56 */
1N/A#ifndef DEFSV
1N/A# define DEFSV GvSV(PL_defgv)
1N/A#endif
1N/A
1N/A#ifndef SAVE_DEFSV
1N/A# define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv))
1N/A#endif
1N/A
1N/A#ifndef newRV_noinc
1N/A# ifdef __GNUC__
1N/A# define newRV_noinc(sv) \
1N/A ({ \
1N/A SV *nsv = (SV*)newRV(sv); \
1N/A SvREFCNT_dec(sv); \
1N/A nsv; \
1N/A })
1N/A# else
1N/A# if defined(USE_THREADS)
1N/Astatic SV * newRV_noinc (SV * sv)
1N/A{
1N/A SV *nsv = (SV*)newRV(sv);
1N/A SvREFCNT_dec(sv);
1N/A return nsv;
1N/A}
1N/A# else
1N/A# define newRV_noinc(sv) \
1N/A (PL_Sv=(SV*)newRV(sv), SvREFCNT_dec(sv), (SV*)PL_Sv)
1N/A# endif
1N/A# endif
1N/A#endif
1N/A
1N/A/* Provide: newCONSTSUB */
1N/A
1N/A/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */
1N/A#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION < 63))
1N/A
1N/A#if defined(NEED_newCONSTSUB)
1N/Astatic
1N/A#else
1N/Aextern void newCONSTSUB(HV * stash, char * name, SV *sv);
1N/A#endif
1N/A
1N/A#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL)
1N/Avoid
1N/AnewCONSTSUB(stash,name,sv)
1N/AHV *stash;
1N/Achar *name;
1N/ASV *sv;
1N/A{
1N/A U32 oldhints = PL_hints;
1N/A HV *old_cop_stash = PL_curcop->cop_stash;
1N/A HV *old_curstash = PL_curstash;
1N/A line_t oldline = PL_curcop->cop_line;
1N/A PL_curcop->cop_line = PL_copline;
1N/A
1N/A PL_hints &= ~HINT_BLOCK_SCOPE;
1N/A if (stash)
1N/A PL_curstash = PL_curcop->cop_stash = stash;
1N/A
1N/A newSUB(
1N/A
1N/A#if (PERL_VERSION < 3) || ((PERL_VERSION == 3) && (PERL_SUBVERSION < 22))
1N/A /* before 5.003_22 */
1N/A start_subparse(),
1N/A#else
1N/A# if (PERL_VERSION == 3) && (PERL_SUBVERSION == 22)
1N/A /* 5.003_22 */
1N/A start_subparse(0),
1N/A# else
1N/A /* 5.003_23 onwards */
1N/A start_subparse(FALSE, 0),
1N/A# endif
1N/A#endif
1N/A
1N/A newSVOP(OP_CONST, 0, newSVpv(name,0)),
1N/A newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */
1N/A newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
1N/A );
1N/A
1N/A PL_hints = oldhints;
1N/A PL_curcop->cop_stash = old_cop_stash;
1N/A PL_curstash = old_curstash;
1N/A PL_curcop->cop_line = oldline;
1N/A}
1N/A#endif
1N/A
1N/A#endif /* newCONSTSUB */
1N/A
1N/A#ifndef START_MY_CXT
1N/A
1N/A/*
1N/A * Boilerplate macros for initializing and accessing interpreter-local
1N/A * data from C. All statics in extensions should be reworked to use
1N/A * this, if you want to make the extension thread-safe. See ext/re/re.xs
1N/A * for an example of the use of these macros.
1N/A *
1N/A * Code that uses these macros is responsible for the following:
1N/A * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
1N/A * 2. Declare a typedef named my_cxt_t that is a structure that contains
1N/A * all the data that needs to be interpreter-local.
1N/A * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
1N/A * 4. Use the MY_CXT_INIT macro such that it is called exactly once
1N/A * (typically put in the BOOT: section).
1N/A * 5. Use the members of the my_cxt_t structure everywhere as
1N/A * MY_CXT.member.
1N/A * 6. Use the dMY_CXT macro (a declaration) in all the functions that
1N/A * access MY_CXT.
1N/A */
1N/A
1N/A#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
1N/A defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT)
1N/A
1N/A/* This must appear in all extensions that define a my_cxt_t structure,
1N/A * right after the definition (i.e. at file scope). The non-threads
1N/A * case below uses it to declare the data as static. */
1N/A#define START_MY_CXT
1N/A
1N/A#if (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION < 68 ))
1N/A/* Fetches the SV that keeps the per-interpreter data. */
1N/A#define dMY_CXT_SV \
1N/A SV *my_cxt_sv = perl_get_sv(MY_CXT_KEY, FALSE)
1N/A#else /* >= perl5.004_68 */
1N/A#define dMY_CXT_SV \
1N/A SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \
1N/A sizeof(MY_CXT_KEY)-1, TRUE)
1N/A#endif /* < perl5.004_68 */
1N/A
1N/A/* This declaration should be used within all functions that use the
1N/A * interpreter-local data. */
1N/A#define dMY_CXT \
1N/A dMY_CXT_SV; \
1N/A my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv))
1N/A
1N/A/* Creates and zeroes the per-interpreter data.
1N/A * (We allocate my_cxtp in a Perl SV so that it will be released when
1N/A * the interpreter goes away.) */
1N/A#define MY_CXT_INIT \
1N/A dMY_CXT_SV; \
1N/A /* newSV() allocates one more than needed */ \
1N/A my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
1N/A Zero(my_cxtp, 1, my_cxt_t); \
1N/A sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
1N/A
1N/A/* This macro must be used to access members of the my_cxt_t structure.
1N/A * e.g. MYCXT.some_data */
1N/A#define MY_CXT (*my_cxtp)
1N/A
1N/A/* Judicious use of these macros can reduce the number of times dMY_CXT
1N/A * is used. Use is similar to pTHX, aTHX etc. */
1N/A#define pMY_CXT my_cxt_t *my_cxtp
1N/A#define pMY_CXT_ pMY_CXT,
1N/A#define _pMY_CXT ,pMY_CXT
1N/A#define aMY_CXT my_cxtp
1N/A#define aMY_CXT_ aMY_CXT,
1N/A#define _aMY_CXT ,aMY_CXT
1N/A
1N/A#else /* single interpreter */
1N/A
1N/A#define START_MY_CXT static my_cxt_t my_cxt;
1N/A#define dMY_CXT_SV dNOOP
1N/A#define dMY_CXT dNOOP
1N/A#define MY_CXT_INIT NOOP
1N/A#define MY_CXT my_cxt
1N/A
1N/A#define pMY_CXT void
1N/A#define pMY_CXT_
1N/A#define _pMY_CXT
1N/A#define aMY_CXT
1N/A#define aMY_CXT_
1N/A#define _aMY_CXT
1N/A
1N/A#endif
1N/A
1N/A#endif /* START_MY_CXT */
1N/A
1N/A#ifndef IVdf
1N/A# if IVSIZE == LONGSIZE
1N/A# define IVdf "ld"
1N/A# define UVuf "lu"
1N/A# define UVof "lo"
1N/A# define UVxf "lx"
1N/A# define UVXf "lX"
1N/A# else
1N/A# if IVSIZE == INTSIZE
1N/A# define IVdf "d"
1N/A# define UVuf "u"
1N/A# define UVof "o"
1N/A# define UVxf "x"
1N/A# define UVXf "X"
1N/A# endif
1N/A# endif
1N/A#endif
1N/A
1N/A#ifndef NVef
1N/A# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \
1N/A defined(PERL_PRIfldbl) /* Not very likely, but let's try anyway. */
1N/A# define NVef PERL_PRIeldbl
1N/A# define NVff PERL_PRIfldbl
1N/A# define NVgf PERL_PRIgldbl
1N/A# else
1N/A# define NVef "e"
1N/A# define NVff "f"
1N/A# define NVgf "g"
1N/A# endif
1N/A#endif
1N/A
1N/A#ifndef AvFILLp /* Older perls (<=5.003) lack AvFILLp */
1N/A# define AvFILLp AvFILL
1N/A#endif
1N/A
1N/A#ifdef SvPVbyte
1N/A# if PERL_REVISION == 5 && PERL_VERSION < 7
1N/A /* SvPVbyte does not work in perl-5.6.1, borrowed version for 5.7.3 */
1N/A# undef SvPVbyte
1N/A# define SvPVbyte(sv, lp) \
1N/A ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \
1N/A ? ((lp = SvCUR(sv)), SvPVX(sv)) : my_sv_2pvbyte(aTHX_ sv, &lp))
1N/A static char *
1N/A my_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *lp)
1N/A {
1N/A sv_utf8_downgrade(sv,0);
1N/A return SvPV(sv,*lp);
1N/A }
1N/A# endif
1N/A#else
1N/A# define SvPVbyte SvPV
1N/A#endif
1N/A
1N/A#ifndef SvPV_nolen
1N/A# define SvPV_nolen(sv) \
1N/A ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
1N/A ? SvPVX(sv) : sv_2pv_nolen(sv))
1N/A static char *
1N/A sv_2pv_nolen(pTHX_ register SV *sv)
1N/A {
1N/A STRLEN n_a;
1N/A return sv_2pv(sv, &n_a);
1N/A }
1N/A#endif
1N/A
1N/A#ifndef get_cv
1N/A# define get_cv(name,create) perl_get_cv(name,create)
1N/A#endif
1N/A
1N/A#ifndef get_sv
1N/A# define get_sv(name,create) perl_get_sv(name,create)
1N/A#endif
1N/A
1N/A#ifndef get_av
1N/A# define get_av(name,create) perl_get_av(name,create)
1N/A#endif
1N/A
1N/A#ifndef get_hv
1N/A# define get_hv(name,create) perl_get_hv(name,create)
1N/A#endif
1N/A
1N/A#ifndef call_argv
1N/A# define call_argv perl_call_argv
1N/A#endif
1N/A
1N/A#ifndef call_method
1N/A# define call_method perl_call_method
1N/A#endif
1N/A
1N/A#ifndef call_pv
1N/A# define call_pv perl_call_pv
1N/A#endif
1N/A
1N/A#ifndef call_sv
1N/A# define call_sv perl_call_sv
1N/A#endif
1N/A
1N/A#ifndef eval_pv
1N/A# define eval_pv perl_eval_pv
1N/A#endif
1N/A
1N/A#ifndef eval_sv
1N/A# define eval_sv perl_eval_sv
1N/A#endif
1N/A
1N/A#ifndef PERL_SCAN_GREATER_THAN_UV_MAX
1N/A# define PERL_SCAN_GREATER_THAN_UV_MAX 0x02
1N/A#endif
1N/A
1N/A#ifndef PERL_SCAN_SILENT_ILLDIGIT
1N/A# define PERL_SCAN_SILENT_ILLDIGIT 0x04
1N/A#endif
1N/A
1N/A#ifndef PERL_SCAN_ALLOW_UNDERSCORES
1N/A# define PERL_SCAN_ALLOW_UNDERSCORES 0x01
1N/A#endif
1N/A
1N/A#ifndef PERL_SCAN_DISALLOW_PREFIX
1N/A# define PERL_SCAN_DISALLOW_PREFIX 0x02
1N/A#endif
1N/A
1N/A#if (PERL_VERSION > 6) || ((PERL_VERSION == 6) && (PERL_SUBVERSION >= 1))
1N/A#define I32_CAST
1N/A#else
1N/A#define I32_CAST (I32*)
1N/A#endif
1N/A
1N/A#ifndef grok_hex
1N/Astatic UV _grok_hex (char *string, STRLEN *len, I32 *flags, NV *result) {
1N/A NV r = scan_hex(string, *len, I32_CAST len);
1N/A if (r > UV_MAX) {
1N/A *flags |= PERL_SCAN_GREATER_THAN_UV_MAX;
1N/A if (result) *result = r;
1N/A return UV_MAX;
1N/A }
1N/A return (UV)r;
1N/A}
1N/A
1N/A# define grok_hex(string, len, flags, result) \
1N/A _grok_hex((string), (len), (flags), (result))
1N/A#endif
1N/A
1N/A#ifndef grok_oct
1N/Astatic UV _grok_oct (char *string, STRLEN *len, I32 *flags, NV *result) {
1N/A NV r = scan_oct(string, *len, I32_CAST len);
1N/A if (r > UV_MAX) {
1N/A *flags |= PERL_SCAN_GREATER_THAN_UV_MAX;
1N/A if (result) *result = r;
1N/A return UV_MAX;
1N/A }
1N/A return (UV)r;
1N/A}
1N/A
1N/A# define grok_oct(string, len, flags, result) \
1N/A _grok_oct((string), (len), (flags), (result))
1N/A#endif
1N/A
1N/A#if !defined(grok_bin) && defined(scan_bin)
1N/Astatic UV _grok_bin (char *string, STRLEN *len, I32 *flags, NV *result) {
1N/A NV r = scan_bin(string, *len, I32_CAST len);
1N/A if (r > UV_MAX) {
1N/A *flags |= PERL_SCAN_GREATER_THAN_UV_MAX;
1N/A if (result) *result = r;
1N/A return UV_MAX;
1N/A }
1N/A return (UV)r;
1N/A}
1N/A
1N/A# define grok_bin(string, len, flags, result) \
1N/A _grok_bin((string), (len), (flags), (result))
1N/A#endif
1N/A
1N/A#ifndef IN_LOCALE
1N/A# define IN_LOCALE \
1N/A (PL_curcop == &PL_compiling ? IN_LOCALE_COMPILETIME : IN_LOCALE_RUNTIME)
1N/A#endif
1N/A
1N/A#ifndef IN_LOCALE_RUNTIME
1N/A# define IN_LOCALE_RUNTIME (PL_curcop->op_private & HINT_LOCALE)
1N/A#endif
1N/A
1N/A#ifndef IN_LOCALE_COMPILETIME
1N/A# define IN_LOCALE_COMPILETIME (PL_hints & HINT_LOCALE)
1N/A#endif
1N/A
1N/A
1N/A#ifndef IS_NUMBER_IN_UV
1N/A# define IS_NUMBER_IN_UV 0x01
1N/A# define IS_NUMBER_GREATER_THAN_UV_MAX 0x02
1N/A# define IS_NUMBER_NOT_INT 0x04
1N/A# define IS_NUMBER_NEG 0x08
1N/A# define IS_NUMBER_INFINITY 0x10
1N/A# define IS_NUMBER_NAN 0x20
1N/A#endif
1N/A
1N/A#ifndef grok_numeric_radix
1N/A# define GROK_NUMERIC_RADIX(sp, send) grok_numeric_radix(aTHX_ sp, send)
1N/A
1N/A#define grok_numeric_radix Perl_grok_numeric_radix
1N/A
1N/Abool
1N/APerl_grok_numeric_radix(pTHX_ const char **sp, const char *send)
1N/A{
1N/A#ifdef USE_LOCALE_NUMERIC
1N/A#if (PERL_VERSION > 6) || ((PERL_VERSION == 6) && (PERL_SUBVERSION >= 1))
1N/A if (PL_numeric_radix_sv && IN_LOCALE) {
1N/A STRLEN len;
1N/A char* radix = SvPV(PL_numeric_radix_sv, len);
1N/A if (*sp + len <= send && memEQ(*sp, radix, len)) {
1N/A *sp += len;
1N/A return TRUE;
1N/A }
1N/A }
1N/A#else
1N/A /* pre5.6.0 perls don't have PL_numeric_radix_sv so the radix
1N/A * must manually be requested from locale.h */
1N/A#include <locale.h>
1N/A struct lconv *lc = localeconv();
1N/A char *radix = lc->decimal_point;
1N/A if (radix && IN_LOCALE) {
1N/A STRLEN len = strlen(radix);
1N/A if (*sp + len <= send && memEQ(*sp, radix, len)) {
1N/A *sp += len;
1N/A return TRUE;
1N/A }
1N/A }
1N/A#endif /* PERL_VERSION */
1N/A#endif /* USE_LOCALE_NUMERIC */
1N/A /* always try "." if numeric radix didn't match because
1N/A * we may have data from different locales mixed */
1N/A if (*sp < send && **sp == '.') {
1N/A ++*sp;
1N/A return TRUE;
1N/A }
1N/A return FALSE;
1N/A}
1N/A#endif /* grok_numeric_radix */
1N/A
1N/A#ifndef grok_number
1N/A
1N/A#define grok_number Perl_grok_number
1N/A
1N/Aint
1N/APerl_grok_number(pTHX_ const char *pv, STRLEN len, UV *valuep)
1N/A{
1N/A const char *s = pv;
1N/A const char *send = pv + len;
1N/A const UV max_div_10 = UV_MAX / 10;
1N/A const char max_mod_10 = UV_MAX % 10;
1N/A int numtype = 0;
1N/A int sawinf = 0;
1N/A int sawnan = 0;
1N/A
1N/A while (s < send && isSPACE(*s))
1N/A s++;
1N/A if (s == send) {
1N/A return 0;
1N/A } else if (*s == '-') {
1N/A s++;
1N/A numtype = IS_NUMBER_NEG;
1N/A }
1N/A else if (*s == '+')
1N/A s++;
1N/A
1N/A if (s == send)
1N/A return 0;
1N/A
1N/A /* next must be digit or the radix separator or beginning of infinity */
1N/A if (isDIGIT(*s)) {
1N/A /* UVs are at least 32 bits, so the first 9 decimal digits cannot
1N/A overflow. */
1N/A UV value = *s - '0';
1N/A /* This construction seems to be more optimiser friendly.
1N/A (without it gcc does the isDIGIT test and the *s - '0' separately)
1N/A With it gcc on arm is managing 6 instructions (6 cycles) per digit.
1N/A In theory the optimiser could deduce how far to unroll the loop
1N/A before checking for overflow. */
1N/A if (++s < send) {
1N/A int digit = *s - '0';
1N/A if (digit >= 0 && digit <= 9) {
1N/A value = value * 10 + digit;
1N/A if (++s < send) {
1N/A digit = *s - '0';
1N/A if (digit >= 0 && digit <= 9) {
1N/A value = value * 10 + digit;
1N/A if (++s < send) {
1N/A digit = *s - '0';
1N/A if (digit >= 0 && digit <= 9) {
1N/A value = value * 10 + digit;
1N/A if (++s < send) {
1N/A digit = *s - '0';
1N/A if (digit >= 0 && digit <= 9) {
1N/A value = value * 10 + digit;
1N/A if (++s < send) {
1N/A digit = *s - '0';
1N/A if (digit >= 0 && digit <= 9) {
1N/A value = value * 10 + digit;
1N/A if (++s < send) {
1N/A digit = *s - '0';
1N/A if (digit >= 0 && digit <= 9) {
1N/A value = value * 10 + digit;
1N/A if (++s < send) {
1N/A digit = *s - '0';
1N/A if (digit >= 0 && digit <= 9) {
1N/A value = value * 10 + digit;
1N/A if (++s < send) {
1N/A digit = *s - '0';
1N/A if (digit >= 0 && digit <= 9) {
1N/A value = value * 10 + digit;
1N/A if (++s < send) {
1N/A /* Now got 9 digits, so need to check
1N/A each time for overflow. */
1N/A digit = *s - '0';
1N/A while (digit >= 0 && digit <= 9
1N/A && (value < max_div_10
1N/A || (value == max_div_10
1N/A && digit <= max_mod_10))) {
1N/A value = value * 10 + digit;
1N/A if (++s < send)
1N/A digit = *s - '0';
1N/A else
1N/A break;
1N/A }
1N/A if (digit >= 0 && digit <= 9
1N/A && (s < send)) {
1N/A /* value overflowed.
1N/A skip the remaining digits, don't
1N/A worry about setting *valuep. */
1N/A do {
1N/A s++;
1N/A } while (s < send && isDIGIT(*s));
1N/A numtype |=
1N/A IS_NUMBER_GREATER_THAN_UV_MAX;
1N/A goto skip_value;
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A }
1N/A numtype |= IS_NUMBER_IN_UV;
1N/A if (valuep)
1N/A *valuep = value;
1N/A
1N/A skip_value:
1N/A if (GROK_NUMERIC_RADIX(&s, send)) {
1N/A numtype |= IS_NUMBER_NOT_INT;
1N/A while (s < send && isDIGIT(*s)) /* optional digits after the radix */
1N/A s++;
1N/A }
1N/A }
1N/A else if (GROK_NUMERIC_RADIX(&s, send)) {
1N/A numtype |= IS_NUMBER_NOT_INT | IS_NUMBER_IN_UV; /* valuep assigned below */
1N/A /* no digits before the radix means we need digits after it */
1N/A if (s < send && isDIGIT(*s)) {
1N/A do {
1N/A s++;
1N/A } while (s < send && isDIGIT(*s));
1N/A if (valuep) {
1N/A /* integer approximation is valid - it's 0. */
1N/A *valuep = 0;
1N/A }
1N/A }
1N/A else
1N/A return 0;
1N/A } else if (*s == 'I' || *s == 'i') {
1N/A s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
1N/A s++; if (s == send || (*s != 'F' && *s != 'f')) return 0;
1N/A s++; if (s < send && (*s == 'I' || *s == 'i')) {
1N/A s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
1N/A s++; if (s == send || (*s != 'I' && *s != 'i')) return 0;
1N/A s++; if (s == send || (*s != 'T' && *s != 't')) return 0;
1N/A s++; if (s == send || (*s != 'Y' && *s != 'y')) return 0;
1N/A s++;
1N/A }
1N/A sawinf = 1;
1N/A } else if (*s == 'N' || *s == 'n') {
1N/A /* XXX TODO: There are signaling NaNs and quiet NaNs. */
1N/A s++; if (s == send || (*s != 'A' && *s != 'a')) return 0;
1N/A s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
1N/A s++;
1N/A sawnan = 1;
1N/A } else
1N/A return 0;
1N/A
1N/A if (sawinf) {
1N/A numtype &= IS_NUMBER_NEG; /* Keep track of sign */
1N/A numtype |= IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT;
1N/A } else if (sawnan) {
1N/A numtype &= IS_NUMBER_NEG; /* Keep track of sign */
1N/A numtype |= IS_NUMBER_NAN | IS_NUMBER_NOT_INT;
1N/A } else if (s < send) {
1N/A /* we can have an optional exponent part */
1N/A if (*s == 'e' || *s == 'E') {
1N/A /* The only flag we keep is sign. Blow away any "it's UV" */
1N/A numtype &= IS_NUMBER_NEG;
1N/A numtype |= IS_NUMBER_NOT_INT;
1N/A s++;
1N/A if (s < send && (*s == '-' || *s == '+'))
1N/A s++;
1N/A if (s < send && isDIGIT(*s)) {
1N/A do {
1N/A s++;
1N/A } while (s < send && isDIGIT(*s));
1N/A }
1N/A else
1N/A return 0;
1N/A }
1N/A }
1N/A while (s < send && isSPACE(*s))
1N/A s++;
1N/A if (s >= send)
1N/A return numtype;
1N/A if (len == 10 && memEQ(pv, "0 but true", 10)) {
1N/A if (valuep)
1N/A *valuep = 0;
1N/A return IS_NUMBER_IN_UV;
1N/A }
1N/A return 0;
1N/A}
1N/A#endif /* grok_number */
1N/A
1N/A#ifndef PERL_MAGIC_sv
1N/A# define PERL_MAGIC_sv '\0'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_overload
1N/A# define PERL_MAGIC_overload 'A'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_overload_elem
1N/A# define PERL_MAGIC_overload_elem 'a'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_overload_table
1N/A# define PERL_MAGIC_overload_table 'c'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_bm
1N/A# define PERL_MAGIC_bm 'B'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_regdata
1N/A# define PERL_MAGIC_regdata 'D'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_regdatum
1N/A# define PERL_MAGIC_regdatum 'd'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_env
1N/A# define PERL_MAGIC_env 'E'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_envelem
1N/A# define PERL_MAGIC_envelem 'e'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_fm
1N/A# define PERL_MAGIC_fm 'f'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_regex_global
1N/A# define PERL_MAGIC_regex_global 'g'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_isa
1N/A# define PERL_MAGIC_isa 'I'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_isaelem
1N/A# define PERL_MAGIC_isaelem 'i'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_nkeys
1N/A# define PERL_MAGIC_nkeys 'k'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_dbfile
1N/A# define PERL_MAGIC_dbfile 'L'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_dbline
1N/A# define PERL_MAGIC_dbline 'l'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_mutex
1N/A# define PERL_MAGIC_mutex 'm'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_shared
1N/A# define PERL_MAGIC_shared 'N'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_shared_scalar
1N/A# define PERL_MAGIC_shared_scalar 'n'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_collxfrm
1N/A# define PERL_MAGIC_collxfrm 'o'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_tied
1N/A# define PERL_MAGIC_tied 'P'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_tiedelem
1N/A# define PERL_MAGIC_tiedelem 'p'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_tiedscalar
1N/A# define PERL_MAGIC_tiedscalar 'q'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_qr
1N/A# define PERL_MAGIC_qr 'r'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_sig
1N/A# define PERL_MAGIC_sig 'S'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_sigelem
1N/A# define PERL_MAGIC_sigelem 's'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_taint
1N/A# define PERL_MAGIC_taint 't'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_uvar
1N/A# define PERL_MAGIC_uvar 'U'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_uvar_elem
1N/A# define PERL_MAGIC_uvar_elem 'u'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_vstring
1N/A# define PERL_MAGIC_vstring 'V'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_vec
1N/A# define PERL_MAGIC_vec 'v'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_utf8
1N/A# define PERL_MAGIC_utf8 'w'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_substr
1N/A# define PERL_MAGIC_substr 'x'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_defelem
1N/A# define PERL_MAGIC_defelem 'y'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_glob
1N/A# define PERL_MAGIC_glob '*'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_arylen
1N/A# define PERL_MAGIC_arylen '#'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_pos
1N/A# define PERL_MAGIC_pos '.'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_backref
1N/A# define PERL_MAGIC_backref '<'
1N/A#endif
1N/A
1N/A#ifndef PERL_MAGIC_ext
1N/A# define PERL_MAGIC_ext '~'
1N/A#endif
1N/A
1N/A#endif /* _P_P_PORTABILITY_H_ */
1N/A
1N/A/* End of File ppport.h */