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