Blame PPPort_pm.PL

Packit 7d6a7d
################################################################################
Packit 7d6a7d
#
Packit 7d6a7d
#  PPPort_pm.PL -- generate PPPort.pm
Packit 7d6a7d
#
Packit 7d6a7d
################################################################################
Packit 7d6a7d
#
Packit 7d6a7d
#  Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz.
Packit 7d6a7d
#  Version 2.x, Copyright (C) 2001, Paul Marquess.
Packit 7d6a7d
#  Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
Packit 7d6a7d
#
Packit 7d6a7d
#  This program is free software; you can redistribute it and/or
Packit 7d6a7d
#  modify it under the same terms as Perl itself.
Packit 7d6a7d
#
Packit 7d6a7d
################################################################################
Packit 7d6a7d
Packit 7d6a7d
use strict;
Packit 7d6a7d
$^W = 1;
Packit 7d6a7d
require "./parts/ppptools.pl";
Packit 7d6a7d
Packit 7d6a7d
my $INCLUDE = 'parts/inc';
Packit 7d6a7d
my $DPPP = 'DPPP_';
Packit 7d6a7d
Packit 7d6a7d
my %embed = map { ( $_->{name} => $_ ) }
Packit 7d6a7d
            parse_embed(qw(parts/embed.fnc parts/apidoc.fnc parts/ppport.fnc));
Packit 7d6a7d
Packit 7d6a7d
my(%provides, %prototypes, %explicit);
Packit 7d6a7d
Packit 7d6a7d
my $data = do { local $/; <DATA> };
Packit 7d6a7d
$data =~ s{^\%(include)\s+(\w+)((?:[^\S\r\n]+.*?)?)\s*$}
Packit 7d6a7d
          {eval "$1('$2', $3)" or die $@}gem;
Packit 7d6a7d
Packit 7d6a7d
$data = expand($data);
Packit 7d6a7d
Packit 7d6a7d
my @api = sort { lc $a cmp lc $b or $a cmp $b } keys %provides;
Packit 7d6a7d
Packit 7d6a7d
$data =~ s{^(.*)__PROVIDED_API__(\s*?)^}
Packit 7d6a7d
          {join '', map "$1$_\n", @api}gem;
Packit 7d6a7d
Packit 7d6a7d
{
Packit 7d6a7d
  my $len = 0;
Packit 7d6a7d
  for (keys %explicit) {
Packit 7d6a7d
    length > $len and $len = length;
Packit 7d6a7d
  }
Packit 7d6a7d
  my $format = sprintf '%%-%ds  %%-%ds  %%s', $len+2, $len+5;
Packit 7d6a7d
  $len = 3*$len + 23;
Packit 7d6a7d
Packit 7d6a7d
$data =~ s!^(.*)__EXPLICIT_API__(\s*?)^!
Packit 7d6a7d
           sprintf("$1$format\n", 'Function / Variable', 'Static Request', 'Global Request') .
Packit 7d6a7d
           $1 . '-'x$len . "\n" .
Packit 7d6a7d
           join('', map { sprintf "$1$format\n", $explicit{$_} eq 'var' ? $_ : "$_()", "NEED_$_", "NEED_${_}_GLOBAL" }
Packit 7d6a7d
                    sort keys %explicit)
Packit 7d6a7d
          !gem;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
my %raw_base = %{&parse_todo('parts/base')};
Packit 7d6a7d
my %raw_todo = %{&parse_todo('parts/todo')};
Packit 7d6a7d
Packit 7d6a7d
my %todo;
Packit 7d6a7d
for (keys %raw_todo) {
Packit 7d6a7d
  push @{$todo{$raw_todo{$_}}}, $_;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
# check consistency
Packit 7d6a7d
for (@api) {
Packit 7d6a7d
  if (exists $raw_todo{$_} and exists $raw_base{$_}) {
Packit 7d6a7d
    if ($raw_base{$_} eq $raw_todo{$_}) {
Packit 7d6a7d
      warn "$INCLUDE/$provides{$_} provides $_, which is still marked "
Packit 7d6a7d
           . "todo for " . format_version($raw_todo{$_}) . "\n";
Packit 7d6a7d
    }
Packit 7d6a7d
    else {
Packit 7d6a7d
      check(2, "$_ was ported back to " . format_version($raw_todo{$_}) .
Packit 7d6a7d
               " (baseline revision: " . format_version($raw_base{$_}) . ").");
Packit 7d6a7d
    }
Packit 7d6a7d
  }
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
my @perl_api;
Packit 7d6a7d
for (keys %provides) {
Packit 7d6a7d
  next if /^Perl_(.*)/ && exists $embed{$1};
Packit 7d6a7d
  next if exists $embed{$_};
Packit 7d6a7d
  push @perl_api, $_;
Packit 7d6a7d
  check(2, "No API definition for provided element $_ found.");
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
push @perl_api, keys %embed;
Packit 7d6a7d
Packit 7d6a7d
for (@perl_api) {
Packit 7d6a7d
  if (exists $provides{$_} && !exists $raw_base{$_}) {
Packit 7d6a7d
    check(2, "Mmmh, $_ doesn't seem to need backporting.");
Packit 7d6a7d
  }
Packit 7d6a7d
  my $line = "$_|" . (exists $provides{$_} && exists $raw_base{$_} ? $raw_base{$_} : '') . '|';
Packit 7d6a7d
  $line .= ($raw_todo{$_} || '') . '|';
Packit 7d6a7d
  $line .= 'p' if exists $provides{$_};
Packit 7d6a7d
  if (exists $embed{$_}) {
Packit 7d6a7d
    my $e = $embed{$_};
Packit 7d6a7d
    if (exists $e->{flags}{p}) {
Packit 7d6a7d
      my $args = $e->{args};
Packit 7d6a7d
      $line .= 'v' if @$args && $args->[-1][0] eq '...';
Packit 7d6a7d
    }
Packit 7d6a7d
    $line .= 'n' if exists $e->{flags}{n};
Packit 7d6a7d
  }
Packit 7d6a7d
  $_ = $line;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
$data =~ s/^([\t ]*)__PERL_API__(\s*?)$/
Packit 7d6a7d
           join "\n", map "$1$_", sort @perl_api
Packit 7d6a7d
          /gem;
Packit 7d6a7d
Packit 7d6a7d
my @todo;
Packit 7d6a7d
for (reverse sort keys %todo) {
Packit 7d6a7d
  my $ver = format_version($_);
Packit 7d6a7d
  my $todo = "=item perl $ver\n\n";
Packit 7d6a7d
  for (sort @{$todo{$_}}) {
Packit 7d6a7d
    $todo .= "  $_\n";
Packit 7d6a7d
  }
Packit 7d6a7d
  push @todo, $todo;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
$data =~ s{^__UNSUPPORTED_API__(\s*?)^}
Packit 7d6a7d
          {join "\n", @todo}gem;
Packit 7d6a7d
Packit 7d6a7d
$data =~ s{__MIN_PERL__}{5.003}g;
Packit 7d6a7d
$data =~ s{__MAX_PERL__}{5.20}g;
Packit 7d6a7d
Packit 7d6a7d
open FH, ">PPPort.pm" or die "PPPort.pm: $!\n";
Packit 7d6a7d
print FH $data;
Packit 7d6a7d
close FH;
Packit 7d6a7d
Packit 7d6a7d
exit 0;
Packit 7d6a7d
Packit 7d6a7d
sub include
Packit 7d6a7d
{
Packit 7d6a7d
  my($file, $opt) = @_;
Packit 7d6a7d
Packit 7d6a7d
  print "including $file\n";
Packit 7d6a7d
Packit 7d6a7d
  my $data = parse_partspec("$INCLUDE/$file");
Packit 7d6a7d
Packit 7d6a7d
  for (@{$data->{provides}}) {
Packit 7d6a7d
    if (exists $provides{$_}) {
Packit 7d6a7d
      if ($provides{$_} ne $file) {
Packit 7d6a7d
        warn "$file: $_ already provided by $provides{$_}\n";
Packit 7d6a7d
      }
Packit 7d6a7d
    }
Packit 7d6a7d
    else {
Packit 7d6a7d
      $provides{$_} = $file;
Packit 7d6a7d
    }
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  for (keys %{$data->{prototypes}}) {
Packit 7d6a7d
    $prototypes{$_} = $data->{prototypes}{$_};
Packit 7d6a7d
    $data->{implementation} =~ s/^$_(?=\s*\()/$DPPP(my_$_)/mg;
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  my $out = $data->{implementation};
Packit 7d6a7d
Packit 7d6a7d
  if (exists $opt->{indent}) {
Packit 7d6a7d
    $out =~ s/^/$opt->{indent}/gm;
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  return $out;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub expand
Packit 7d6a7d
{
Packit 7d6a7d
  my $code = shift;
Packit 7d6a7d
  $code =~ s{^(\s*#\s*(?:el)?if\s+)(.*)$}{$1.expand_pp_expressions($2)}gem;
Packit 7d6a7d
  $code =~ s{^\s*
Packit 7d6a7d
              __UNDEFINED__
Packit 7d6a7d
              \s+
Packit 7d6a7d
              (
Packit 7d6a7d
                ( \w+ )
Packit 7d6a7d
                (?: \( [^)]* \) )?
Packit 7d6a7d
              )
Packit 7d6a7d
              [^\r\n\S]*
Packit 7d6a7d
              (
Packit 7d6a7d
                (?:[^\r\n\\]|\\[^\r\n])*
Packit 7d6a7d
                (?:
Packit 7d6a7d
                  \\
Packit 7d6a7d
                  (?:\r\n|[\r\n])
Packit 7d6a7d
                  (?:[^\r\n\\]|\\[^\r\n])*
Packit 7d6a7d
                )*
Packit 7d6a7d
              )
Packit 7d6a7d
            \s*$}
Packit 7d6a7d
            {expand_undefined($2, $1, $3)}gemx;
Packit 7d6a7d
  $code =~ s{^([^\S\r\n]*)__NEED_VAR__\s+(.*?)\s+(\w+)(?:\s*=\s*([^;]+?))?\s*;\s*$}
Packit 7d6a7d
            {expand_need_var($1, $3, $2, $4)}gem;
Packit 7d6a7d
  $code =~ s{^([^\S\r\n]*)__NEED_DUMMY_VAR__\s+(.*?)\s+(\w+)(?:\s*=\s*([^;]+?))?\s*;\s*$}
Packit 7d6a7d
            {expand_need_dummy_var($1, $3, $2, $4)}gem;
Packit 7d6a7d
  return $code;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub expand_need_var
Packit 7d6a7d
{
Packit 7d6a7d
  my($indent, $var, $type, $init) = @_;
Packit 7d6a7d
Packit 7d6a7d
  $explicit{$var} = 'var';
Packit 7d6a7d
Packit 7d6a7d
  my $myvar = "$DPPP(my_$var)";
Packit 7d6a7d
  $init = defined $init ? " = $init" : "";
Packit 7d6a7d
Packit 7d6a7d
  my $code = <
Packit 7d6a7d
#if defined(NEED_$var)
Packit 7d6a7d
static $type $myvar$init;
Packit 7d6a7d
#elif defined(NEED_${var}_GLOBAL)
Packit 7d6a7d
$type $myvar$init;
Packit 7d6a7d
#else
Packit 7d6a7d
extern $type $myvar;
Packit 7d6a7d
#endif
Packit 7d6a7d
#define $var $myvar
Packit 7d6a7d
ENDCODE
Packit 7d6a7d
Packit 7d6a7d
  $code =~ s/^/$indent/mg;
Packit 7d6a7d
Packit 7d6a7d
  return $code;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub expand_need_dummy_var
Packit 7d6a7d
{
Packit 7d6a7d
  my($indent, $var, $type, $init) = @_;
Packit 7d6a7d
Packit 7d6a7d
  $explicit{$var} = 'var';
Packit 7d6a7d
Packit 7d6a7d
  my $myvar = "$DPPP(dummy_$var)";
Packit 7d6a7d
  $init = defined $init ? " = $init" : "";
Packit 7d6a7d
Packit 7d6a7d
  my $code = <
Packit 7d6a7d
#if defined(NEED_$var)
Packit 7d6a7d
static $type $myvar$init;
Packit 7d6a7d
#elif defined(NEED_${var}_GLOBAL)
Packit 7d6a7d
$type $myvar$init;
Packit 7d6a7d
#else
Packit 7d6a7d
extern $type $myvar;
Packit 7d6a7d
#endif
Packit 7d6a7d
ENDCODE
Packit 7d6a7d
Packit 7d6a7d
  $code =~ s/^/$indent/mg;
Packit 7d6a7d
Packit 7d6a7d
  return $code;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub expand_undefined
Packit 7d6a7d
{
Packit 7d6a7d
  my($macro, $withargs, $def) = @_;
Packit 7d6a7d
  my $rv = "#ifndef $macro\n#  define ";
Packit 7d6a7d
Packit 7d6a7d
  if (defined $def && $def =~ /\S/) {
Packit 7d6a7d
    $rv .= sprintf "%-30s %s", $withargs, $def;
Packit 7d6a7d
  }
Packit 7d6a7d
  else {
Packit 7d6a7d
    $rv .= $withargs;
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  $rv .= "\n#endif\n";
Packit 7d6a7d
Packit 7d6a7d
  return $rv;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub expand_pp_expressions
Packit 7d6a7d
{
Packit 7d6a7d
  my $pp = shift;
Packit 7d6a7d
  $pp =~ s/\{([^\}]+)\}/expand_pp_expr($1)/ge;
Packit 7d6a7d
  return $pp;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub expand_pp_expr
Packit 7d6a7d
{
Packit 7d6a7d
  my $expr = shift;
Packit 7d6a7d
Packit 7d6a7d
  if ($expr =~ /^\s*need\s+(\w+)\s*$/i) {
Packit 7d6a7d
    my $func = $1;
Packit 7d6a7d
    my $e = $embed{$func} or die "unknown API function '$func' in NEED\n";
Packit 7d6a7d
    my $proto = make_prototype($e);
Packit 7d6a7d
    if (exists $prototypes{$func}) {
Packit 7d6a7d
      if (compare_prototypes($proto, $prototypes{$func})) {
Packit 7d6a7d
        check(1, "differing prototypes for $func:\n  API: $proto\n  PPP: $prototypes{$func}");
Packit 7d6a7d
        $proto = $prototypes{$func};
Packit 7d6a7d
      }
Packit 7d6a7d
    }
Packit 7d6a7d
    else {
Packit 7d6a7d
      warn "found no prototype for $func\n";;
Packit 7d6a7d
    }
Packit 7d6a7d
Packit 7d6a7d
    $explicit{$func} = 'func';
Packit 7d6a7d
Packit 7d6a7d
    $proto =~ s/\b$func(?=\s*\()/$DPPP(my_$func)/;
Packit 7d6a7d
    my $embed = make_embed($e);
Packit 7d6a7d
Packit 7d6a7d
    return "defined(NEED_$func)\n"
Packit 7d6a7d
         . "static $proto;\n"
Packit 7d6a7d
         . "static\n"
Packit 7d6a7d
         . "#else\n"
Packit 7d6a7d
         . "extern $proto;\n"
Packit 7d6a7d
         . "#endif\n"
Packit 7d6a7d
         . "\n"
Packit 7d6a7d
         . "$embed\n"
Packit 7d6a7d
         . "\n"
Packit 7d6a7d
         . "#if defined(NEED_$func) || defined(NEED_${func}_GLOBAL)";
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  die "cannot expand preprocessor expression '$expr'\n";
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub make_embed
Packit 7d6a7d
{
Packit 7d6a7d
  my $f = shift;
Packit 7d6a7d
  my $n = $f->{name};
Packit 7d6a7d
  my $a = do { my $x = 'a'; join ',', map { $x++ } 1 .. @{$f->{args}} };
Packit 7d6a7d
  my $lastarg = ${$f->{args}}[-1];
Packit 7d6a7d
Packit 7d6a7d
  if ($f->{flags}{n}) {
Packit 7d6a7d
    if ($f->{flags}{p}) {
Packit 7d6a7d
      return "#define $n $DPPP(my_$n)\n" .
Packit 7d6a7d
             "#define Perl_$n $DPPP(my_$n)";
Packit 7d6a7d
    }
Packit 7d6a7d
    else {
Packit 7d6a7d
      return "#define $n $DPPP(my_$n)";
Packit 7d6a7d
    }
Packit 7d6a7d
  }
Packit 7d6a7d
  else {
Packit 7d6a7d
    my $undef = <
Packit 7d6a7d
#ifdef $n
Packit 7d6a7d
#  undef $n
Packit 7d6a7d
#endif
Packit 7d6a7d
UNDEF
Packit 7d6a7d
    if ($f->{flags}{p}) {
Packit 7d6a7d
      if ($f->{flags}{f}) {
Packit 7d6a7d
        return "#define Perl_$n $DPPP(my_$n)";
Packit 7d6a7d
      }
Packit 7d6a7d
      elsif (@$lastarg && $lastarg->[0] =~ /\.\.\./) {
Packit 7d6a7d
        return $undef . "#define $n $DPPP(my_$n)\n" .
Packit 7d6a7d
                        "#define Perl_$n $DPPP(my_$n)";
Packit 7d6a7d
      }
Packit 7d6a7d
      else {
Packit 7d6a7d
        return $undef . "#define $n($a) $DPPP(my_$n)(aTHX_ $a)\n" .
Packit 7d6a7d
                        "#define Perl_$n $DPPP(my_$n)";
Packit 7d6a7d
      }
Packit 7d6a7d
    }
Packit 7d6a7d
    else {
Packit 7d6a7d
      return $undef . "#define $n($a) $DPPP(my_$n)(aTHX_ $a)";
Packit 7d6a7d
    }
Packit 7d6a7d
  }
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub check
Packit 7d6a7d
{
Packit 7d6a7d
  my $level = shift;
Packit 7d6a7d
Packit 7d6a7d
  if (exists $ENV{DPPP_CHECK_LEVEL} and $ENV{DPPP_CHECK_LEVEL} >= $level) {
Packit 7d6a7d
    print STDERR @_, "\n";
Packit 7d6a7d
  }
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
__DATA__
Packit 7d6a7d
################################################################################
Packit 7d6a7d
#
Packit 7d6a7d
#  !!!!! Do NOT edit this file directly! -- Edit PPPort_pm.PL instead. !!!!!
Packit 7d6a7d
#
Packit 7d6a7d
#  This file was automatically generated from the definition files in the
Packit 7d6a7d
#  parts/inc/ subdirectory by PPPort_pm.PL. To learn more about how all this
Packit 7d6a7d
#  works, please read the F<HACKERS> file that came with this distribution.
Packit 7d6a7d
#
Packit 7d6a7d
################################################################################
Packit 7d6a7d
#
Packit 7d6a7d
#  Perl/Pollution/Portability
Packit 7d6a7d
#
Packit 7d6a7d
################################################################################
Packit 7d6a7d
#
Packit 7d6a7d
#  Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz.
Packit 7d6a7d
#  Version 2.x, Copyright (C) 2001, Paul Marquess.
Packit 7d6a7d
#  Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
Packit 7d6a7d
#
Packit 7d6a7d
#  This program is free software; you can redistribute it and/or
Packit 7d6a7d
#  modify it under the same terms as Perl itself.
Packit 7d6a7d
#
Packit 7d6a7d
################################################################################
Packit 7d6a7d
Packit 7d6a7d
=head1 NAME
Packit 7d6a7d
Packit 7d6a7d
Devel::PPPort - Perl/Pollution/Portability
Packit 7d6a7d
Packit 7d6a7d
=head1 SYNOPSIS
Packit 7d6a7d
Packit 7d6a7d
    Devel::PPPort::WriteFile();   # defaults to ./ppport.h
Packit 7d6a7d
    Devel::PPPort::WriteFile('someheader.h');
Packit 7d6a7d
Packit 7d6a7d
    # Same as above but retrieve contents rather than write file
Packit 7d6a7d
    my $contents = Devel::PPPort::GetFileContents();
Packit 7d6a7d
    my $contents = Devel::PPPort::GetFileContents('someheader.h');
Packit 7d6a7d
Packit 7d6a7d
=head1 DESCRIPTION
Packit 7d6a7d
Packit 7d6a7d
Perl's API has changed over time, gaining new features, new functions,
Packit 7d6a7d
increasing its flexibility, and reducing the impact on the C namespace
Packit 7d6a7d
environment (reduced pollution). The header file written by this module,
Packit 7d6a7d
typically F<ppport.h>, attempts to bring some of the newer Perl API
Packit 7d6a7d
features to older versions of Perl, so that you can worry less about
Packit 7d6a7d
keeping track of old releases, but users can still reap the benefit.
Packit 7d6a7d
Packit 7d6a7d
C<Devel::PPPort> contains two functions, C<WriteFile> and C<GetFileContents>.
Packit 7d6a7d
C<WriteFile>'s only purpose is to write the F<ppport.h> C header file.
Packit 7d6a7d
This file contains a series of macros and, if explicitly requested, functions
Packit 7d6a7d
that allow XS modules to be built using older versions of Perl. Currently,
Packit 7d6a7d
Perl versions from __MIN_PERL__ to __MAX_PERL__ are supported.
Packit 7d6a7d
Packit 7d6a7d
C<GetFileContents> can be used to retrieve the file contents rather than
Packit 7d6a7d
writing it out.
Packit 7d6a7d
Packit 7d6a7d
This module is used by C<h2xs> to write the file F<ppport.h>.
Packit 7d6a7d
Packit 7d6a7d
=head2 Why use ppport.h?
Packit 7d6a7d
Packit 7d6a7d
You should use F<ppport.h> in modern code so that your code will work
Packit 7d6a7d
with the widest range of Perl interpreters possible, without significant
Packit 7d6a7d
additional work.
Packit 7d6a7d
Packit 7d6a7d
You should attempt older code to fully use F<ppport.h>, because the
Packit 7d6a7d
reduced pollution of newer Perl versions is an important thing. It's so
Packit 7d6a7d
important that the old polluting ways of original Perl modules will not be
Packit 7d6a7d
supported very far into the future, and your module will almost certainly
Packit 7d6a7d
break! By adapting to it now, you'll gain compatibility and a sense of
Packit 7d6a7d
having done the electronic ecology some good.
Packit 7d6a7d
Packit 7d6a7d
=head2 How to use ppport.h
Packit 7d6a7d
Packit 7d6a7d
Don't direct the users of your module to download C<Devel::PPPort>.
Packit 7d6a7d
They are most probably no XS writers. Also, don't make F<ppport.h>
Packit 7d6a7d
optional. Rather, just take the most recent copy of F<ppport.h> that
Packit 7d6a7d
you can find (e.g. by generating it with the latest C<Devel::PPPort>
Packit 7d6a7d
release from CPAN), copy it into your project, adjust your project to
Packit 7d6a7d
use it, and distribute the header along with your module.
Packit 7d6a7d
Packit 7d6a7d
=head2 Running ppport.h
Packit 7d6a7d
Packit 7d6a7d
But F<ppport.h> is more than just a C header. It's also a Perl script
Packit 7d6a7d
that can check your source code. It will suggest hints and portability
Packit 7d6a7d
notes, and can even make suggestions on how to change your code. You
Packit 7d6a7d
can run it like any other Perl program:
Packit 7d6a7d
Packit 7d6a7d
    perl ppport.h [options] [files]
Packit 7d6a7d
Packit 7d6a7d
It also has embedded documentation, so you can use
Packit 7d6a7d
Packit 7d6a7d
    perldoc ppport.h
Packit 7d6a7d
Packit 7d6a7d
to find out more about how to use it.
Packit 7d6a7d
Packit 7d6a7d
=head1 FUNCTIONS
Packit 7d6a7d
Packit 7d6a7d
=head2 WriteFile
Packit 7d6a7d
Packit 7d6a7d
C<WriteFile> takes one optional argument. When called with one
Packit 7d6a7d
argument, it expects to be passed a filename. When called with
Packit 7d6a7d
no arguments, it defaults to the filename F<ppport.h>.
Packit 7d6a7d
Packit 7d6a7d
The function returns a true value if the file was written successfully.
Packit 7d6a7d
Otherwise it returns a false value.
Packit 7d6a7d
Packit 7d6a7d
=head2 GetFileContents
Packit 7d6a7d
Packit 7d6a7d
C<GetFileContents> behaves like C<WriteFile> above, but returns the contents
Packit 7d6a7d
of the would-be file rather than writing it out.
Packit 7d6a7d
Packit 7d6a7d
=head1 COMPATIBILITY
Packit 7d6a7d
Packit 7d6a7d
F<ppport.h> supports Perl versions from __MIN_PERL__ to __MAX_PERL__
Packit 7d6a7d
in threaded and non-threaded configurations.
Packit 7d6a7d
Packit 7d6a7d
=head2 Provided Perl compatibility API
Packit 7d6a7d
Packit 7d6a7d
The header file written by this module, typically F<ppport.h>, provides
Packit 7d6a7d
access to the following elements of the Perl API that is not available
Packit 7d6a7d
in older Perl releases:
Packit 7d6a7d
Packit 7d6a7d
    __PROVIDED_API__
Packit 7d6a7d
Packit 7d6a7d
=head2 Perl API not supported by ppport.h
Packit 7d6a7d
Packit 7d6a7d
There is still a big part of the API not supported by F<ppport.h>.
Packit 7d6a7d
Either because it doesn't make sense to back-port that part of the API,
Packit 7d6a7d
or simply because it hasn't been implemented yet. Patches welcome!
Packit 7d6a7d
Packit 7d6a7d
Here's a list of the currently unsupported API, and also the version of
Packit 7d6a7d
Perl below which it is unsupported:
Packit 7d6a7d
Packit 7d6a7d
=over 4
Packit 7d6a7d
Packit 7d6a7d
__UNSUPPORTED_API__
Packit 7d6a7d
Packit 7d6a7d
=back
Packit 7d6a7d
Packit 7d6a7d
=head1 BUGS
Packit 7d6a7d
Packit 7d6a7d
If you find any bugs, C<Devel::PPPort> doesn't seem to build on your
Packit 7d6a7d
system, or any of its tests fail, please file an issue here:
Packit 7d6a7d
L<https://github.com/mhx/Devel-PPPort/issues/>
Packit 7d6a7d
Packit 7d6a7d
=head1 AUTHORS
Packit 7d6a7d
Packit 7d6a7d
=over 2
Packit 7d6a7d
Packit 7d6a7d
=item *
Packit 7d6a7d
Packit 7d6a7d
Version 1.x of Devel::PPPort was written by Kenneth Albanowski.
Packit 7d6a7d
Packit 7d6a7d
=item *
Packit 7d6a7d
Packit 7d6a7d
Version 2.x was ported to the Perl core by Paul Marquess.
Packit 7d6a7d
Packit 7d6a7d
=item *
Packit 7d6a7d
Packit 7d6a7d
Version 3.x was ported back to CPAN by Marcus Holland-Moritz.
Packit 7d6a7d
Packit 7d6a7d
=item * 
Packit 7d6a7d
Packit 7d6a7d
Versions >= 3.22 are maintained with support from Matthew Horsfall (alh).
Packit 7d6a7d
Packit 7d6a7d
=back
Packit 7d6a7d
Packit 7d6a7d
=head1 COPYRIGHT
Packit 7d6a7d
Packit 7d6a7d
Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz.
Packit 7d6a7d
Packit 7d6a7d
Version 2.x, Copyright (C) 2001, Paul Marquess.
Packit 7d6a7d
Packit 7d6a7d
Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
Packit 7d6a7d
Packit 7d6a7d
This program is free software; you can redistribute it and/or
Packit 7d6a7d
modify it under the same terms as Perl itself.
Packit 7d6a7d
Packit 7d6a7d
=head1 SEE ALSO
Packit 7d6a7d
Packit 7d6a7d
See L<h2xs>, L<ppport.h>.
Packit 7d6a7d
Packit 7d6a7d
=cut
Packit 7d6a7d
Packit 7d6a7d
package Devel::PPPort;
Packit 7d6a7d
Packit 7d6a7d
use strict;
Packit 7d6a7d
use vars qw($VERSION $data);
Packit 7d6a7d
Packit 7d6a7d
$VERSION = '3.36';
Packit 7d6a7d
Packit 7d6a7d
sub _init_data
Packit 7d6a7d
{
Packit 7d6a7d
  $data = do { local $/; <DATA> };
Packit 7d6a7d
  my $pkg = 'Devel::PPPort';
Packit 7d6a7d
  $data =~ s/__PERL_VERSION__/$]/g;
Packit 7d6a7d
  $data =~ s/__VERSION__/$VERSION/g;
Packit 7d6a7d
  $data =~ s/__PKG__/$pkg/g;
Packit 7d6a7d
  $data =~ s/^\|>//gm;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub GetFileContents {
Packit 7d6a7d
  my $file = shift || 'ppport.h';
Packit 7d6a7d
  defined $data or _init_data();
Packit 7d6a7d
  my $copy = $data;
Packit 7d6a7d
  $copy =~ s/\bppport\.h\b/$file/g;
Packit 7d6a7d
Packit 7d6a7d
  return $copy;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub WriteFile
Packit 7d6a7d
{
Packit 7d6a7d
  my $file = shift || 'ppport.h';
Packit 7d6a7d
  my $data = GetFileContents($file);
Packit 7d6a7d
  open F, ">$file" or return undef;
Packit 7d6a7d
  print F $data;
Packit 7d6a7d
  close F;
Packit 7d6a7d
Packit 7d6a7d
  return 1;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
1;
Packit 7d6a7d
Packit 7d6a7d
__DATA__
Packit 7d6a7d
#if 0
Packit 7d6a7d
<<'SKIP';
Packit 7d6a7d
#endif
Packit 7d6a7d
/*
Packit 7d6a7d
----------------------------------------------------------------------
Packit 7d6a7d
Packit 7d6a7d
    ppport.h -- Perl/Pollution/Portability Version __VERSION__
Packit 7d6a7d
Packit 7d6a7d
    Automatically created by __PKG__ running under perl __PERL_VERSION__.
Packit 7d6a7d
Packit 7d6a7d
    Do NOT edit this file directly! -- Edit PPPort_pm.PL and the
Packit 7d6a7d
    includes in parts/inc/ instead.
Packit 7d6a7d
Packit 7d6a7d
    Use 'perldoc ppport.h' to view the documentation below.
Packit 7d6a7d
Packit 7d6a7d
----------------------------------------------------------------------
Packit 7d6a7d
Packit 7d6a7d
SKIP
Packit 7d6a7d
Packit 7d6a7d
%include ppphdoc { indent => '|>' }
Packit 7d6a7d
Packit 7d6a7d
%include ppphbin
Packit 7d6a7d
Packit 7d6a7d
__DATA__
Packit 7d6a7d
*/
Packit 7d6a7d
Packit 7d6a7d
#ifndef _P_P_PORTABILITY_H_
Packit 7d6a7d
#define _P_P_PORTABILITY_H_
Packit 7d6a7d
Packit 7d6a7d
#ifndef DPPP_NAMESPACE
Packit 7d6a7d
#  define DPPP_NAMESPACE DPPP_
Packit 7d6a7d
#endif
Packit 7d6a7d
Packit 7d6a7d
#define DPPP_CAT2(x,y) CAT2(x,y)
Packit 7d6a7d
#define DPPP_(name) DPPP_CAT2(DPPP_NAMESPACE, name)
Packit 7d6a7d
Packit 7d6a7d
%include version
Packit 7d6a7d
Packit 7d6a7d
%include threads
Packit 7d6a7d
Packit 7d6a7d
%include limits
Packit 7d6a7d
Packit 7d6a7d
%include uv
Packit 7d6a7d
Packit 7d6a7d
%include memory
Packit 7d6a7d
Packit 7d6a7d
%include misc
Packit 7d6a7d
Packit 7d6a7d
%include variables
Packit 7d6a7d
Packit 7d6a7d
%include mPUSH
Packit 7d6a7d
Packit 7d6a7d
%include call
Packit 7d6a7d
Packit 7d6a7d
%include newRV
Packit 7d6a7d
Packit 7d6a7d
%include newCONSTSUB
Packit 7d6a7d
Packit 7d6a7d
%include MY_CXT
Packit 7d6a7d
Packit 7d6a7d
%include format
Packit 7d6a7d
Packit 7d6a7d
%include SvREFCNT
Packit 7d6a7d
Packit 7d6a7d
%include newSV_type
Packit 7d6a7d
Packit 7d6a7d
%include newSVpv
Packit 7d6a7d
Packit 7d6a7d
%include SvPV
Packit 7d6a7d
Packit 7d6a7d
%include Sv_set
Packit 7d6a7d
Packit 7d6a7d
%include sv_xpvf
Packit 7d6a7d
Packit 7d6a7d
%include shared_pv
Packit 7d6a7d
Packit 7d6a7d
%include HvNAME
Packit 7d6a7d
Packit 7d6a7d
%include gv
Packit 7d6a7d
Packit 7d6a7d
%include warn
Packit 7d6a7d
Packit 7d6a7d
%include pvs
Packit 7d6a7d
Packit 7d6a7d
%include magic
Packit 7d6a7d
Packit 7d6a7d
%include cop
Packit 7d6a7d
Packit 7d6a7d
%include grok
Packit 7d6a7d
Packit 7d6a7d
%include snprintf
Packit 7d6a7d
Packit 7d6a7d
%include sprintf
Packit 7d6a7d
Packit 7d6a7d
%include exception
Packit 7d6a7d
Packit 7d6a7d
%include strlfuncs
Packit 7d6a7d
Packit 7d6a7d
%include pv_tools
Packit 7d6a7d
Packit 7d6a7d
#endif /* _P_P_PORTABILITY_H_ */
Packit 7d6a7d
Packit 7d6a7d
/* End of File ppport.h */