Upgrade to Devel::PPPort 3.08_01
[p5sagit/p5-mst-13.2.git] / ext / 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#
f2ab5a41 8# $Revision: 16 $
adfe19db 9# $Author: mhx $
f2ab5a41 10# $Date: 2006/05/19 16:15:51 +0200 $
adfe19db 11#
12################################################################################
13#
0d0f8426 14# Version 3.x, Copyright (C) 2004-2006, 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) {
27 open OUT, ">$ARGV[0]" or die "$ARGV[0]: $!\n";
28}
29else {
30 *OUT = \*STDOUT;
31}
32
33my @f = parse_embed(qw( parts/embed.fnc parts/apidoc.fnc ));
34
35my %todo = %{&parse_todo};
36
37my %tmap = (
38 void => 'int',
39);
40
41my %amap = (
42 SP => 'SP',
43 type => 'int',
44 cast => 'int',
45);
46
47my %void = (
48 void => 1,
49 Free_t => 1,
50 Signal_t => 1,
51);
52
53my %castvoid = (
54 map { ($_ => 1) } qw(
55 Nullav
56 Nullcv
57 Nullhv
58 Nullch
59 Nullsv
60 HEf_SVKEY
61 SP
62 MARK
63 SVt_PV
64 SVt_IV
65 SVt_NV
66 SVt_PVMG
67 SVt_PVAV
68 SVt_PVHV
69 SVt_PVCV
70 SvUOK
71 G_SCALAR
72 G_ARRAY
73 G_VOID
74 G_DISCARD
75 G_EVAL
76 G_NOARGS
77 XS_VERSION
78 ),
79);
80
81my %ignorerv = (
82 map { ($_ => 1) } qw(
83 newCONSTSUB
84 ),
85);
86
87my %stack = (
4a582685 88 ORIGMARK => ['dORIGMARK;'],
89 POPpx => ['STRLEN n_a;'],
90 POPpbytex => ['STRLEN n_a;'],
91 PUSHp => ['dTARG;'],
92 PUSHn => ['dTARG;'],
93 PUSHi => ['dTARG;'],
94 PUSHu => ['dTARG;'],
95 XPUSHp => ['dTARG;'],
96 XPUSHn => ['dTARG;'],
97 XPUSHi => ['dTARG;'],
98 XPUSHu => ['dTARG;'],
99 UNDERBAR => ['dUNDERBAR;'],
100 XCPT_TRY_START => ['dXCPT;'],
101 XCPT_TRY_END => ['dXCPT;'],
102 XCPT_CATCH => ['dXCPT;'],
103 XCPT_RETHROW => ['dXCPT;'],
adfe19db 104);
105
106my %postcode = (
107 dSP => "some_global_var = !sp;",
108 dMARK => "some_global_var = !mark;",
109 dORIGMARK => "some_global_var = !origmark;",
110 dAX => "some_global_var = !ax;",
111 dITEMS => "some_global_var = !items;",
112 dXSARGS => "some_global_var = ax && items;",
113 NEWSV => "some_global_var = !arg1;",
114 New => "some_global_var = !arg1;",
115 Newc => "some_global_var = !arg1;",
116 Newz => "some_global_var = !arg1;",
117 dUNDERBAR => "(void) UNDERBAR;",
118);
119
120my %ignore = (
121 map { ($_ => 1) } qw(
122 svtype
123 items
124 ix
125 dXSI32
126 XS
127 CLASS
128 THIS
129 RETVAL
130 StructCopy
131 ),
132);
133
134print OUT <<HEAD;
135/*
136 * !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
137 * This file is built by $0.
138 * Any changes made here will be lost!
139 */
140
141#include "EXTERN.h"
142#include "perl.h"
4a582685 143
144#define NO_XSLOCKS
adfe19db 145#include "XSUB.h"
146
147#ifndef DPPP_APICHECK_NO_PPPORT_H
148
149#define NEED_eval_pv
150#define NEED_grok_bin
151#define NEED_grok_hex
152#define NEED_grok_number
153#define NEED_grok_numeric_radix
154#define NEED_grok_oct
f2ab5a41 155#define NEED_my_snprintf
adfe19db 156#define NEED_newCONSTSUB
157#define NEED_newRV_noinc
158#define NEED_sv_2pv_nolen
159#define NEED_sv_2pvbyte
96ad942f 160#define NEED_sv_catpvf_mg
161#define NEED_sv_catpvf_mg_nocontext
162#define NEED_sv_setpvf_mg
163#define NEED_sv_setpvf_mg_nocontext
164#define NEED_vnewSVpvf
f2ab5a41 165#define NEED_warner
96ad942f 166
adfe19db 167
168#include "ppport.h"
169
170#endif
171
172static int some_global_var;
173
174static int VARarg1;
175static char *VARarg2;
176static double VARarg3;
177
178HEAD
179
180my $f;
181for $f (@f) {
182 $ignore{$f->{name}} and next;
183 $f->{flags}{A} or next; # only public API members
184
185 $ignore{$f->{name}} = 1; # ignore duplicates
186
187 my $Perl_ = $f->{flags}{p} ? 'Perl_' : '';
188
189 my $stack = '';
190 my @arg;
191 my $aTHX = '';
192
193 my $i = 1;
194 my $ca;
195 my $varargs = 0;
196 for $ca (@{$f->{args}}) {
197 my $a = $ca->[0];
198 if ($a eq '...') {
199 $varargs = 1;
200 push @arg, qw(VARarg1 VARarg2 VARarg3);
201 last;
202 }
4a582685 203 my($n, $p, $d) = $a =~ /^ (\w+(?:\s+\w+)*)\s* # type name => $n
204 (\**) # pointer => $p
f2ab5a41 205 (?:\s*const\s*)? # const
4a582685 206 ((?:\[[^\]]*\])*) # dimension => $d
207 $/x
208 or die "$0 - cannot parse argument: [$a]\n";
adfe19db 209 if (exists $amap{$n}) {
210 push @arg, $amap{$n};
211 next;
212 }
213 $n = $tmap{$n} || $n;
214 my $v = 'arg' . $i++;
215 push @arg, $v;
216 $stack .= " static $n $p$v$d;\n";
217 }
218
219 unless ($f->{flags}{n} || $f->{flags}{'m'}) {
220 $stack = " dTHX;\n$stack";
221 $aTHX = @arg ? 'aTHX_ ' : 'aTHX';
222 }
223
224 if ($stack{$f->{name}}) {
225 my $s = '';
226 for (@{$stack{$f->{name}}}) {
227 $s .= " $_\n";
228 }
229 $stack = "$s$stack";
230 }
231
232 my $args = join ', ', @arg;
233 my $rvt = $f->{ret} || 'void';
234 my $ret;
235 if ($void{$rvt}) {
236 $ret = $castvoid{$f->{name}} ? '(void) ' : '';
237 }
238 else {
239 $ret = $ignorerv{$f->{name}} ? '(void) ' : "return ";
240 }
241 my $aTHX_args = "$aTHX$args";
242
243 my $post = '';
244 if ($postcode{$f->{name}}) {
245 $post = $postcode{$f->{name}};
246 $post =~ s/^/ /g;
247 $post = "\n$post";
248 }
249
250 unless ($f->{flags}{'m'} and @arg == 0) {
251 $args = "($args)";
252 $aTHX_args = "($aTHX_args)";
253 }
254
255 print OUT <<HEAD;
256/******************************************************************************
257*
258* $f->{name}
259*
260******************************************************************************/
261
262HEAD
263
264 if ($todo{$f->{name}}) {
265 my($ver,$sub) = $todo{$f->{name}} =~ /^5\.(\d{3})(\d{3})$/ or die;
266 for ($ver, $sub) {
267 s/^0+(\d)/$1/
268 }
269 if ($ver < 6 && $sub > 0) {
270 $sub =~ s/0$// or die;
271 }
272 print OUT "#if PERL_VERSION > $ver || (PERL_VERSION == $ver && PERL_SUBVERSION >= $sub) /* TODO */\n";
273 }
274
275 my $final = $varargs
276 ? "$Perl_$f->{name}$aTHX_args"
277 : "$f->{name}$args";
278
279 $f->{cond} and print OUT "#if $f->{cond}\n";
280
281 print OUT <<END;
282$rvt _DPPP_test_$f->{name} (void)
283{
284 dXSARGS;
285$stack
286#ifdef $f->{name}
287 if (some_global_var)
288 {
289 $ret$f->{name}$args;$post
290 }
291#endif
292
293 some_global_var = items && ax;
294
295 {
296#ifdef $f->{name}
297 $ret$final;$post
298#else
299 $ret$Perl_$f->{name}$aTHX_args;$post
300#endif
301 }
302}
303END
304
305 $f->{cond} and print OUT "#endif\n";
306 $todo{$f->{name}} and print OUT "#endif\n";
307
308 print OUT "\n";
309}
310
311@ARGV and close OUT;
312