|
Packit |
7d6a7d |
#!/usr/bin/perl -w
|
|
Packit |
7d6a7d |
################################################################################
|
|
Packit |
7d6a7d |
#
|
|
Packit |
7d6a7d |
# apicheck.pl -- generate C source for automated API check
|
|
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 |
require './parts/ppptools.pl';
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
if (@ARGV) {
|
|
Packit |
7d6a7d |
my $file = pop @ARGV;
|
|
Packit |
7d6a7d |
open OUT, ">$file" or die "$file: $!\n";
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
else {
|
|
Packit |
7d6a7d |
*OUT = \*STDOUT;
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my @f = parse_embed(qw( parts/embed.fnc parts/apidoc.fnc parts/ppport.fnc ));
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my %todo = %{&parse_todo};
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my %tmap = (
|
|
Packit |
7d6a7d |
void => 'int',
|
|
Packit |
7d6a7d |
);
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my %amap = (
|
|
Packit |
7d6a7d |
SP => 'SP',
|
|
Packit |
7d6a7d |
type => 'int',
|
|
Packit |
7d6a7d |
cast => 'int',
|
|
Packit |
7d6a7d |
);
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my %void = (
|
|
Packit |
7d6a7d |
void => 1,
|
|
Packit |
7d6a7d |
Free_t => 1,
|
|
Packit |
7d6a7d |
Signal_t => 1,
|
|
Packit |
7d6a7d |
);
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my %castvoid = (
|
|
Packit |
7d6a7d |
map { ($_ => 1) } qw(
|
|
Packit |
7d6a7d |
Nullav
|
|
Packit |
7d6a7d |
Nullcv
|
|
Packit |
7d6a7d |
Nullhv
|
|
Packit |
7d6a7d |
Nullch
|
|
Packit |
7d6a7d |
Nullsv
|
|
Packit |
7d6a7d |
HEf_SVKEY
|
|
Packit |
7d6a7d |
SP
|
|
Packit |
7d6a7d |
MARK
|
|
Packit |
7d6a7d |
SVt_PV
|
|
Packit |
7d6a7d |
SVt_IV
|
|
Packit |
7d6a7d |
SVt_NV
|
|
Packit |
7d6a7d |
SVt_PVMG
|
|
Packit |
7d6a7d |
SVt_PVAV
|
|
Packit |
7d6a7d |
SVt_PVHV
|
|
Packit |
7d6a7d |
SVt_PVCV
|
|
Packit |
7d6a7d |
SvUOK
|
|
Packit |
7d6a7d |
G_SCALAR
|
|
Packit |
7d6a7d |
G_ARRAY
|
|
Packit |
7d6a7d |
G_VOID
|
|
Packit |
7d6a7d |
G_DISCARD
|
|
Packit |
7d6a7d |
G_EVAL
|
|
Packit |
7d6a7d |
G_NOARGS
|
|
Packit |
7d6a7d |
XS_VERSION
|
|
Packit |
7d6a7d |
),
|
|
Packit |
7d6a7d |
);
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my %ignorerv = (
|
|
Packit |
7d6a7d |
map { ($_ => 1) } qw(
|
|
Packit |
7d6a7d |
newCONSTSUB
|
|
Packit |
7d6a7d |
),
|
|
Packit |
7d6a7d |
);
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my %stack = (
|
|
Packit |
7d6a7d |
ORIGMARK => ['dORIGMARK;'],
|
|
Packit |
7d6a7d |
POPpx => ['STRLEN n_a;'],
|
|
Packit |
7d6a7d |
POPpbytex => ['STRLEN n_a;'],
|
|
Packit |
7d6a7d |
PUSHp => ['dTARG;'],
|
|
Packit |
7d6a7d |
PUSHn => ['dTARG;'],
|
|
Packit |
7d6a7d |
PUSHi => ['dTARG;'],
|
|
Packit |
7d6a7d |
PUSHu => ['dTARG;'],
|
|
Packit |
7d6a7d |
XPUSHp => ['dTARG;'],
|
|
Packit |
7d6a7d |
XPUSHn => ['dTARG;'],
|
|
Packit |
7d6a7d |
XPUSHi => ['dTARG;'],
|
|
Packit |
7d6a7d |
XPUSHu => ['dTARG;'],
|
|
Packit |
7d6a7d |
UNDERBAR => ['dUNDERBAR;'],
|
|
Packit |
7d6a7d |
XCPT_TRY_START => ['dXCPT;'],
|
|
Packit |
7d6a7d |
XCPT_TRY_END => ['dXCPT;'],
|
|
Packit |
7d6a7d |
XCPT_CATCH => ['dXCPT;'],
|
|
Packit |
7d6a7d |
XCPT_RETHROW => ['dXCPT;'],
|
|
Packit |
7d6a7d |
);
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my %ignore = (
|
|
Packit |
7d6a7d |
map { ($_ => 1) } qw(
|
|
Packit |
7d6a7d |
svtype
|
|
Packit |
7d6a7d |
items
|
|
Packit |
7d6a7d |
ix
|
|
Packit |
7d6a7d |
dXSI32
|
|
Packit |
7d6a7d |
XS
|
|
Packit |
7d6a7d |
CLASS
|
|
Packit |
7d6a7d |
THIS
|
|
Packit |
7d6a7d |
RETVAL
|
|
Packit |
7d6a7d |
StructCopy
|
|
Packit |
7d6a7d |
),
|
|
Packit |
7d6a7d |
);
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
print OUT <
|
|
Packit |
7d6a7d |
/*
|
|
Packit |
7d6a7d |
* !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
|
|
Packit |
7d6a7d |
* This file is built by $0.
|
|
Packit |
7d6a7d |
* Any changes made here will be lost!
|
|
Packit |
7d6a7d |
*/
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#include "EXTERN.h"
|
|
Packit |
7d6a7d |
#include "perl.h"
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#define NO_XSLOCKS
|
|
Packit |
7d6a7d |
#include "XSUB.h"
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#ifdef DPPP_APICHECK_NO_PPPORT_H
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
/* This is just to avoid too many baseline failures with perls < 5.6.0 */
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#ifndef dTHX
|
|
Packit |
7d6a7d |
# define dTHX extern int Perl___notused
|
|
Packit |
7d6a7d |
#endif
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#else
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#define NEED_PL_signals
|
|
Packit |
7d6a7d |
#define NEED_PL_parser
|
|
Packit |
7d6a7d |
#define NEED_caller_cx
|
|
Packit |
7d6a7d |
#define NEED_eval_pv
|
|
Packit |
7d6a7d |
#define NEED_grok_bin
|
|
Packit |
7d6a7d |
#define NEED_grok_hex
|
|
Packit |
7d6a7d |
#define NEED_grok_number
|
|
Packit |
7d6a7d |
#define NEED_grok_numeric_radix
|
|
Packit |
7d6a7d |
#define NEED_grok_oct
|
|
Packit |
7d6a7d |
#define NEED_gv_fetchpvn_flags
|
|
Packit |
7d6a7d |
#define NEED_load_module
|
|
Packit |
7d6a7d |
#define NEED_mg_findext
|
|
Packit |
7d6a7d |
#define NEED_my_snprintf
|
|
Packit |
7d6a7d |
#define NEED_my_sprintf
|
|
Packit |
7d6a7d |
#define NEED_my_strlcat
|
|
Packit |
7d6a7d |
#define NEED_my_strlcpy
|
|
Packit |
7d6a7d |
#define NEED_newCONSTSUB
|
|
Packit |
7d6a7d |
#define NEED_newRV_noinc
|
|
Packit |
7d6a7d |
#define NEED_newSV_type
|
|
Packit |
7d6a7d |
#define NEED_newSVpvn_flags
|
|
Packit |
7d6a7d |
#define NEED_newSVpvn_share
|
|
Packit |
7d6a7d |
#define NEED_pv_display
|
|
Packit |
7d6a7d |
#define NEED_pv_escape
|
|
Packit |
7d6a7d |
#define NEED_pv_pretty
|
|
Packit |
7d6a7d |
#define NEED_sv_2pv_flags
|
|
Packit |
7d6a7d |
#define NEED_sv_2pvbyte
|
|
Packit |
7d6a7d |
#define NEED_sv_catpvf_mg
|
|
Packit |
7d6a7d |
#define NEED_sv_catpvf_mg_nocontext
|
|
Packit |
7d6a7d |
#define NEED_sv_pvn_force_flags
|
|
Packit |
7d6a7d |
#define NEED_sv_setpvf_mg
|
|
Packit |
7d6a7d |
#define NEED_sv_setpvf_mg_nocontext
|
|
Packit |
7d6a7d |
#define NEED_sv_unmagicext
|
|
Packit |
7d6a7d |
#define NEED_SvRX
|
|
Packit |
7d6a7d |
#define NEED_vload_module
|
|
Packit |
7d6a7d |
#define NEED_vnewSVpvf
|
|
Packit |
7d6a7d |
#define NEED_warner
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#include "ppport.h"
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#endif
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
static int VARarg1;
|
|
Packit |
7d6a7d |
static char *VARarg2;
|
|
Packit |
7d6a7d |
static double VARarg3;
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#if defined(PERL_BCDVERSION) && (PERL_BCDVERSION < 0x5009005)
|
|
Packit |
7d6a7d |
/* needed to make PL_parser apicheck work */
|
|
Packit |
7d6a7d |
typedef void yy_parser;
|
|
Packit |
7d6a7d |
#endif
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
HEAD
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
if (@ARGV) {
|
|
Packit |
7d6a7d |
my %want = map { ($_ => 0) } @ARGV;
|
|
Packit |
7d6a7d |
@f = grep { exists $want{$_->{name}} } @f;
|
|
Packit |
7d6a7d |
for (@f) { $want{$_->{name}}++ }
|
|
Packit |
7d6a7d |
for (keys %want) {
|
|
Packit |
7d6a7d |
die "nothing found for '$_'\n" unless $want{$_};
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my $f;
|
|
Packit |
7d6a7d |
for $f (@f) {
|
|
Packit |
7d6a7d |
$ignore{$f->{name}} and next;
|
|
Packit |
7d6a7d |
$f->{flags}{A} or next; # only public API members
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
$ignore{$f->{name}} = 1; # ignore duplicates
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my $Perl_ = $f->{flags}{p} ? 'Perl_' : '';
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my $stack = '';
|
|
Packit |
7d6a7d |
my @arg;
|
|
Packit |
7d6a7d |
my $aTHX = '';
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my $i = 1;
|
|
Packit |
7d6a7d |
my $ca;
|
|
Packit |
7d6a7d |
my $varargs = 0;
|
|
Packit |
7d6a7d |
for $ca (@{$f->{args}}) {
|
|
Packit |
7d6a7d |
my $a = $ca->[0];
|
|
Packit |
7d6a7d |
if ($a eq '...') {
|
|
Packit |
7d6a7d |
$varargs = 1;
|
|
Packit |
7d6a7d |
push @arg, qw(VARarg1 VARarg2 VARarg3);
|
|
Packit |
7d6a7d |
last;
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
my($n, $p, $d) = $a =~ /^ (\w+(?:\s+\w+)*)\s* # type name => $n
|
|
Packit |
7d6a7d |
(\**) # pointer => $p
|
|
Packit |
7d6a7d |
(?:\s*const\s*)? # const
|
|
Packit |
7d6a7d |
((?:\[[^\]]*\])*) # dimension => $d
|
|
Packit |
7d6a7d |
$/x
|
|
Packit |
7d6a7d |
or die "$0 - cannot parse argument: [$a]\n";
|
|
Packit |
7d6a7d |
if (exists $amap{$n}) {
|
|
Packit |
7d6a7d |
push @arg, $amap{$n};
|
|
Packit |
7d6a7d |
next;
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
$n = $tmap{$n} || $n;
|
|
Packit |
7d6a7d |
if ($n eq 'const char' and $p eq '*' and !$f->{flags}{f}) {
|
|
Packit |
7d6a7d |
push @arg, '"foo"';
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
else {
|
|
Packit |
7d6a7d |
my $v = 'arg' . $i++;
|
|
Packit |
7d6a7d |
push @arg, $v;
|
|
Packit |
7d6a7d |
$stack .= " static $n $p$v$d;\n";
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
unless ($f->{flags}{n} || $f->{flags}{'m'}) {
|
|
Packit |
7d6a7d |
$stack = " dTHX;\n$stack";
|
|
Packit |
7d6a7d |
$aTHX = @arg ? 'aTHX_ ' : 'aTHX';
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
if ($stack{$f->{name}}) {
|
|
Packit |
7d6a7d |
my $s = '';
|
|
Packit |
7d6a7d |
for (@{$stack{$f->{name}}}) {
|
|
Packit |
7d6a7d |
$s .= " $_\n";
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
$stack = "$s$stack";
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my $args = join ', ', @arg;
|
|
Packit |
7d6a7d |
my $rvt = $f->{ret} || 'void';
|
|
Packit |
7d6a7d |
my $ret;
|
|
Packit |
7d6a7d |
if ($void{$rvt}) {
|
|
Packit |
7d6a7d |
$ret = $castvoid{$f->{name}} ? '(void) ' : '';
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
else {
|
|
Packit |
7d6a7d |
$stack .= " $rvt rval;\n";
|
|
Packit |
7d6a7d |
$ret = $ignorerv{$f->{name}} ? '(void) ' : "rval = ";
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
my $aTHX_args = "$aTHX$args";
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
if (!$f->{flags}{'m'} or $f->{flags}{'b'} or @arg > 0) {
|
|
Packit |
7d6a7d |
$args = "($args)";
|
|
Packit |
7d6a7d |
$aTHX_args = "($aTHX_args)";
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
print OUT <
|
|
Packit |
7d6a7d |
/******************************************************************************
|
|
Packit |
7d6a7d |
*
|
|
Packit |
7d6a7d |
* $f->{name}
|
|
Packit |
7d6a7d |
*
|
|
Packit |
7d6a7d |
******************************************************************************/
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
HEAD
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
if ($todo{$f->{name}}) {
|
|
Packit |
7d6a7d |
my($ver,$sub) = $todo{$f->{name}} =~ /^5\.(\d{3})(\d{3})$/ or die;
|
|
Packit |
7d6a7d |
for ($ver, $sub) {
|
|
Packit |
7d6a7d |
s/^0+(\d)/$1/
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
if ($ver < 6 && $sub > 0) {
|
|
Packit |
7d6a7d |
$sub =~ s/0$// or die;
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
print OUT "#if PERL_VERSION > $ver || (PERL_VERSION == $ver && PERL_SUBVERSION >= $sub) /* TODO */\n";
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
my $final = $varargs
|
|
Packit |
7d6a7d |
? "$Perl_$f->{name}$aTHX_args"
|
|
Packit |
7d6a7d |
: "$f->{name}$args";
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
$f->{cond} and print OUT "#if $f->{cond}\n";
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
print OUT <
|
|
Packit |
7d6a7d |
void _DPPP_test_$f->{name} (void)
|
|
Packit |
7d6a7d |
{
|
|
Packit |
7d6a7d |
dXSARGS;
|
|
Packit |
7d6a7d |
$stack
|
|
Packit |
7d6a7d |
{
|
|
Packit |
7d6a7d |
#ifdef $f->{name}
|
|
Packit |
7d6a7d |
$ret$f->{name}$args;
|
|
Packit |
7d6a7d |
#endif
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
{
|
|
Packit |
7d6a7d |
#ifdef $f->{name}
|
|
Packit |
7d6a7d |
$ret$final;
|
|
Packit |
7d6a7d |
#else
|
|
Packit |
7d6a7d |
$ret$Perl_$f->{name}$aTHX_args;
|
|
Packit |
7d6a7d |
#endif
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
END
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
$f->{cond} and print OUT "#endif\n";
|
|
Packit |
7d6a7d |
$todo{$f->{name}} and print OUT "#endif\n";
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
print OUT "\n";
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
@ARGV and close OUT;
|