Upgrade to Devel::PPPort 3.19_02
[p5sagit/p5-mst-13.2.git] / cpan / Devel-PPPort / parts / apicheck.pl
CommitLineData
adfe19db 1#!/usr/bin/perl -w
2################################################################################
3#
4# apicheck.pl -- generate C source for automated API check
5#
6################################################################################
7#
bfc37ff7 8# $Revision: 37 $
adfe19db 9# $Author: mhx $
bfc37ff7 10# $Date: 2010/03/07 13:15:43 +0100 $
adfe19db 11#
12################################################################################
13#
bfc37ff7 14# Version 3.x, Copyright (C) 2004-2010, Marcus Holland-Moritz.
adfe19db 15# Version 2.x, Copyright (C) 2001, Paul Marquess.
16# Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
17#
18# This program is free software; you can redistribute it and/or
19# modify it under the same terms as Perl itself.
20#
21################################################################################
22
23use strict;
24require 'parts/ppptools.pl';
25
26if (@ARGV) {
0c96388f 27 my $file = pop @ARGV;
28 open OUT, ">$file" or die "$file: $!\n";
adfe19db 29}
30else {
31 *OUT = \*STDOUT;
32}
33
679ad62d 34my @f = parse_embed(qw( parts/embed.fnc parts/apidoc.fnc parts/ppport.fnc ));
adfe19db 35
36my %todo = %{&parse_todo};
37
38my %tmap = (
39 void => 'int',
40);
41
42my %amap = (
43 SP => 'SP',
44 type => 'int',
45 cast => 'int',
46);
47
48my %void = (
49 void => 1,
50 Free_t => 1,
51 Signal_t => 1,
52);
53
54my %castvoid = (
55 map { ($_ => 1) } qw(
56 Nullav
57 Nullcv
58 Nullhv
59 Nullch
60 Nullsv
61 HEf_SVKEY
62 SP
63 MARK
64 SVt_PV
65 SVt_IV
66 SVt_NV
67 SVt_PVMG
68 SVt_PVAV
69 SVt_PVHV
70 SVt_PVCV
71 SvUOK
72 G_SCALAR
73 G_ARRAY
74 G_VOID
75 G_DISCARD
76 G_EVAL
77 G_NOARGS
78 XS_VERSION
79 ),
80);
81
82my %ignorerv = (
83 map { ($_ => 1) } qw(
84 newCONSTSUB
85 ),
86);
87
88my %stack = (
4a582685 89 ORIGMARK => ['dORIGMARK;'],
90 POPpx => ['STRLEN n_a;'],
91 POPpbytex => ['STRLEN n_a;'],
92 PUSHp => ['dTARG;'],
93 PUSHn => ['dTARG;'],
94 PUSHi => ['dTARG;'],
95 PUSHu => ['dTARG;'],
96 XPUSHp => ['dTARG;'],
97 XPUSHn => ['dTARG;'],
98 XPUSHi => ['dTARG;'],
99 XPUSHu => ['dTARG;'],
100 UNDERBAR => ['dUNDERBAR;'],
101 XCPT_TRY_START => ['dXCPT;'],
102 XCPT_TRY_END => ['dXCPT;'],
103 XCPT_CATCH => ['dXCPT;'],
104 XCPT_RETHROW => ['dXCPT;'],
adfe19db 105);
106
adfe19db 107my %ignore = (
108 map { ($_ => 1) } qw(
109 svtype
110 items
111 ix
112 dXSI32
113 XS
114 CLASS
115 THIS
116 RETVAL
117 StructCopy
118 ),
119);
120
121print OUT <<HEAD;
122/*
123 * !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
124 * This file is built by $0.
125 * Any changes made here will be lost!
126 */
127
128#include "EXTERN.h"
129#include "perl.h"
4a582685 130
131#define NO_XSLOCKS
adfe19db 132#include "XSUB.h"
133
ba120f6f 134#ifdef DPPP_APICHECK_NO_PPPORT_H
135
136/* This is just to avoid too many baseline failures with perls < 5.6.0 */
137
138#ifndef dTHX
139# define dTHX extern int Perl___notused
140#endif
141
142#else
adfe19db 143
679ad62d 144#define NEED_PL_signals
c01be2ce 145#define NEED_PL_parser
adfe19db 146#define NEED_eval_pv
147#define NEED_grok_bin
148#define NEED_grok_hex
149#define NEED_grok_number
150#define NEED_grok_numeric_radix
151#define NEED_grok_oct
679ad62d 152#define NEED_load_module
f2ab5a41 153#define NEED_my_snprintf
c01be2ce 154#define NEED_my_sprintf
aef0a14c 155#define NEED_my_strlcat
156#define NEED_my_strlcpy
adfe19db 157#define NEED_newCONSTSUB
158#define NEED_newRV_noinc
8565c31a 159#define NEED_newSV_type
c83e6f19 160#define NEED_newSVpvn_share
db42c902 161#define NEED_pv_display
162#define NEED_pv_escape
163#define NEED_pv_pretty
679ad62d 164#define NEED_sv_2pv_flags
adfe19db 165#define NEED_sv_2pvbyte
96ad942f 166#define NEED_sv_catpvf_mg
167#define NEED_sv_catpvf_mg_nocontext
c83e6f19 168#define NEED_sv_pvn_force_flags
96ad942f 169#define NEED_sv_setpvf_mg
170#define NEED_sv_setpvf_mg_nocontext
679ad62d 171#define NEED_vload_module
96ad942f 172#define NEED_vnewSVpvf
f2ab5a41 173#define NEED_warner
c1a049cb 174#define NEED_newSVpvn_flags
96ad942f 175
adfe19db 176#include "ppport.h"
177
178#endif
179
adfe19db 180static int VARarg1;
181static char *VARarg2;
182static double VARarg3;
183
184HEAD
185
0c96388f 186if (@ARGV) {
187 my %want = map { ($_ => 0) } @ARGV;
188 @f = grep { exists $want{$_->{name}} } @f;
189 for (@f) { $want{$_->{name}}++ }
190 for (keys %want) {
191 die "nothing found for '$_'\n" unless $want{$_};
192 }
193}
194
adfe19db 195my $f;
196for $f (@f) {
197 $ignore{$f->{name}} and next;
198 $f->{flags}{A} or next; # only public API members
199
200 $ignore{$f->{name}} = 1; # ignore duplicates
201
202 my $Perl_ = $f->{flags}{p} ? 'Perl_' : '';
203
204 my $stack = '';
205 my @arg;
206 my $aTHX = '';
207
208 my $i = 1;
209 my $ca;
210 my $varargs = 0;
211 for $ca (@{$f->{args}}) {
212 my $a = $ca->[0];
213 if ($a eq '...') {
214 $varargs = 1;
215 push @arg, qw(VARarg1 VARarg2 VARarg3);
216 last;
217 }
4a582685 218 my($n, $p, $d) = $a =~ /^ (\w+(?:\s+\w+)*)\s* # type name => $n
219 (\**) # pointer => $p
f2ab5a41 220 (?:\s*const\s*)? # const
4a582685 221 ((?:\[[^\]]*\])*) # dimension => $d
222 $/x
223 or die "$0 - cannot parse argument: [$a]\n";
adfe19db 224 if (exists $amap{$n}) {
225 push @arg, $amap{$n};
226 next;
227 }
228 $n = $tmap{$n} || $n;
0c96388f 229 if ($n eq 'const char' and $p eq '*' and !$f->{flags}{f}) {
230 push @arg, '"foo"';
231 }
232 else {
233 my $v = 'arg' . $i++;
234 push @arg, $v;
235 $stack .= " static $n $p$v$d;\n";
236 }
adfe19db 237 }
238
239 unless ($f->{flags}{n} || $f->{flags}{'m'}) {
240 $stack = " dTHX;\n$stack";
241 $aTHX = @arg ? 'aTHX_ ' : 'aTHX';
242 }
243
244 if ($stack{$f->{name}}) {
245 my $s = '';
246 for (@{$stack{$f->{name}}}) {
247 $s .= " $_\n";
248 }
249 $stack = "$s$stack";
250 }
251
252 my $args = join ', ', @arg;
253 my $rvt = $f->{ret} || 'void';
254 my $ret;
255 if ($void{$rvt}) {
256 $ret = $castvoid{$f->{name}} ? '(void) ' : '';
257 }
258 else {
ba120f6f 259 $stack .= " $rvt rval;\n";
260 $ret = $ignorerv{$f->{name}} ? '(void) ' : "rval = ";
adfe19db 261 }
262 my $aTHX_args = "$aTHX$args";
263
bfc37ff7 264 if (!$f->{flags}{'m'} or $f->{flags}{'b'} or @arg > 0) {
adfe19db 265 $args = "($args)";
266 $aTHX_args = "($aTHX_args)";
267 }
268
269 print OUT <<HEAD;
270/******************************************************************************
271*
272* $f->{name}
273*
274******************************************************************************/
275
276HEAD
277
278 if ($todo{$f->{name}}) {
279 my($ver,$sub) = $todo{$f->{name}} =~ /^5\.(\d{3})(\d{3})$/ or die;
280 for ($ver, $sub) {
281 s/^0+(\d)/$1/
282 }
283 if ($ver < 6 && $sub > 0) {
284 $sub =~ s/0$// or die;
285 }
286 print OUT "#if PERL_VERSION > $ver || (PERL_VERSION == $ver && PERL_SUBVERSION >= $sub) /* TODO */\n";
287 }
288
289 my $final = $varargs
290 ? "$Perl_$f->{name}$aTHX_args"
291 : "$f->{name}$args";
292
293 $f->{cond} and print OUT "#if $f->{cond}\n";
294
295 print OUT <<END;
ba120f6f 296void _DPPP_test_$f->{name} (void)
adfe19db 297{
298 dXSARGS;
299$stack
adfe19db 300 {
ba120f6f 301#ifdef $f->{name}
302 $ret$f->{name}$args;
adfe19db 303#endif
ba120f6f 304 }
adfe19db 305
306 {
307#ifdef $f->{name}
ba120f6f 308 $ret$final;
adfe19db 309#else
ba120f6f 310 $ret$Perl_$f->{name}$aTHX_args;
adfe19db 311#endif
312 }
313}
314END
315
316 $f->{cond} and print OUT "#endif\n";
317 $todo{$f->{name}} and print OUT "#endif\n";
318
319 print OUT "\n";
320}
321
322@ARGV and close OUT;
323