This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regen/HeaderParser.pm - A module to parse our header files
[perl5.git] / regen / embed.pl
CommitLineData
5f05dabc 1#!/usr/bin/perl -w
f1e99d0d 2#
6294c161
DM
3# Regenerate (overwriting only if changed):
4#
5# embed.h
6# embedvar.h
6294c161
DM
7# proto.h
8#
9# from information stored in
10#
11# embed.fnc
12# intrpvar.h
13# perlvars.h
897d3989 14# regen/opcodes
6294c161 15#
6294c161
DM
16# Accepts the standard regen_lib -q and -v args.
17#
18# This script is normally invoked from regen.pl.
e50aee73 19
916e4025 20require 5.004; # keep this compatible, an old perl is all we may have before
954c1994 21 # we build the new one
5f05dabc 22
88e01c9d
AL
23use strict;
24
36bb303b
NC
25BEGIN {
26 # Get function prototypes
3d7c117d
MB
27 require './regen/regen_lib.pl';
28 require './regen/embed_lib.pl';
36bb303b
NC
29}
30
916e4025 31my $unflagged_pointers;
88e01c9d 32
cea2e8a9 33#
346f75ff 34# See database of global and static function prototypes in embed.fnc
cea2e8a9
GS
35# This is used to generate prototype headers under various configurations,
36# export symbols lists for different platforms, and macros to provide an
37# implicit interpreter context argument.
38#
39
eeec122d
KW
40my $error_count = 0;
41sub die_at_end ($) { # Keeps going for now, but makes sure the regen doesn't
42 # succeed.
43 warn shift;
44 $error_count++;
45}
46
03b6588a 47sub full_name ($$) { # Returns the function name with potentially the
9824c081 48 # prefixes 'S_' or 'Perl_'
03b6588a
KW
49 my ($func, $flags) = @_;
50
c43e2db5 51 return "Perl_$func" if $flags =~ /[ps]/;
f1e99d0d 52 return "S_$func" if $flags =~ /[SIi]/;
03b6588a
KW
53 return $func;
54}
55
5f8dc073 56sub open_print_header {
56fd1190 57 my ($file, $quote) = @_;
4373e329 58
5f8dc073 59 return open_new($file, '>',
9824c081
MS
60 { file => $file, style => '*', by => 'regen/embed.pl',
61 from => ['data in embed.fnc', 'regen/embed.pl',
62 'regen/opcodes', 'intrpvar.h', 'perlvars.h'],
63 final => "\nEdit those files and run 'make regen_headers' to effect changes.\n",
64 copyright => [1993 .. 2009], quote => $quote });
5f8dc073 65}
7f1be197 66
5ccbf88e
NC
67my ($embed, $core, $ext, $api) = setup_embed();
68
cea2e8a9 69# generate proto.h
9516dc40 70{
5f8dc073
NC
71 my $pr = open_print_header("proto.h");
72 print $pr "START_EXTERN_C\n";
f8394530 73 my $ret;
9516dc40 74
5ccbf88e 75 foreach (@$embed) {
9824c081
MS
76 if (@$_ == 1) {
77 print $pr "$_->[0]\n";
78 next;
79 }
9516dc40 80
9824c081 81 my ($flags,$retval,$plain_func,@args) = @$_;
c43e2db5 82 if ($flags =~ / ( [^AabCDdEefFGhIiMmNnOoPpRrSsTUuWXx;] ) /x) {
9824c081
MS
83 die_at_end "flag $1 is not legal (for function $plain_func)";
84 }
85 my @nonnull;
86 my $args_assert_line = ( $flags !~ /G/ );
21553840 87 my $has_depth = ( $flags =~ /W/ );
9824c081
MS
88 my $has_context = ( $flags !~ /T/ );
89 my $never_returns = ( $flags =~ /r/ );
90 my $binarycompat = ( $flags =~ /b/ );
91 my $commented_out = ( $flags =~ /m/ );
92 my $is_malloc = ( $flags =~ /a/ );
93 my $can_ignore = ( $flags !~ /R/ ) && ( $flags !~ /P/ ) && !$is_malloc;
94 my @names_of_nn;
95 my $func;
96
97 if (! $can_ignore && $retval eq 'void') {
98 warn "It is nonsensical to require the return value of a void function ($plain_func) to be checked";
99 }
100
101 die_at_end "$plain_func: S and p flags are mutually exclusive"
102 if $flags =~ /S/ && $flags =~ /p/;
103 die_at_end "$plain_func: m and $1 flags are mutually exclusive"
104 if $flags =~ /m/ && $flags =~ /([pS])/;
105
106 die_at_end "$plain_func: u flag only usable with m" if $flags =~ /u/
107 && $flags !~ /m/;
108
109 my $static_inline = 0;
c43e2db5 110 if ($flags =~ /([SsIi])/) {
9824c081
MS
111 my $type;
112 if ($never_returns) {
113 $type = {
114 'S' => 'PERL_STATIC_NO_RET',
c43e2db5 115 's' => 'PERL_STATIC_NO_RET',
9824c081
MS
116 'i' => 'PERL_STATIC_INLINE_NO_RET',
117 'I' => 'PERL_STATIC_FORCE_INLINE_NO_RET'
118 }->{$1};
119 }
120 else {
121 $type = {
122 'S' => 'STATIC',
c43e2db5 123 's' => 'STATIC',
9824c081
MS
124 'i' => 'PERL_STATIC_INLINE',
125 'I' => 'PERL_STATIC_FORCE_INLINE'
126 }->{$1};
127 }
128 $retval = "$type $retval";
129 die_at_end "Don't declare static function '$plain_func' pure" if $flags =~ /P/;
130 $static_inline = $type =~ /^PERL_STATIC(?:_FORCE)?_INLINE/;
131 }
132 else {
133 if ($never_returns) {
134 $retval = "PERL_CALLCONV_NO_RET $retval";
135 }
136 else {
137 $retval = "PERL_CALLCONV $retval";
138 }
139 }
140
3f394718
KW
141 $func = full_name($plain_func, $flags);
142
9824c081
MS
143 die_at_end "For '$plain_func', M flag requires p flag"
144 if $flags =~ /M/ && $flags !~ /p/;
c43e2db5 145 my $C_required_flags = '[pIimbs]';
07b6261f
KW
146 die_at_end
147 "For '$plain_func', C flag requires one of $C_required_flags] flags"
148 if $flags =~ /C/
149 && ($flags !~ /$C_required_flags/
150
151 # Notwithstanding the
152 # above, if the name won't
153 # clash with a user name,
154 # it's ok.
155 && $plain_func !~ /^[Pp]erl/);
3f394718 156
9824c081
MS
157 die_at_end "For '$plain_func', X flag requires one of [Iip] flags"
158 if $flags =~ /X/ && $flags !~ /[Iip]/;
159 die_at_end "For '$plain_func', X and m flags are mutually exclusive"
160 if $flags =~ /X/ && $flags =~ /m/;
161 die_at_end "For '$plain_func', [Ii] with [ACX] requires p flag"
162 if $flags =~ /[Ii]/ && $flags =~ /[ACX]/ && $flags !~ /p/;
163 die_at_end "For '$plain_func', b and m flags are mutually exclusive"
164 . " (try M flag)" if $flags =~ /b/ && $flags =~ /m/;
165 die_at_end "For '$plain_func', b flag without M flag requires D flag"
166 if $flags =~ /b/ && $flags !~ /M/ && $flags !~ /D/;
167 die_at_end "For '$plain_func', I and i flags are mutually exclusive"
168 if $flags =~ /I/ && $flags =~ /i/;
169
9824c081
MS
170 $ret = "";
171 $ret .= "$retval\t$func(";
172 if ( $has_context ) {
173 $ret .= @args ? "pTHX_ " : "pTHX";
174 }
175 if (@args) {
176 die_at_end "n flag is contradicted by having arguments"
177 if $flags =~ /n/;
178 my $n;
179 for my $arg ( @args ) {
180 ++$n;
fd4fc0f6
KW
181 if ($arg =~ / ^ " (.+) " $ /x) { # Handle literal string
182 my $name = $1;
183
184 # Make the string a legal C identifier; 'p' is arbitrary,
185 # and is because C reserves leading underscores
186 $name =~ s/^\W/p/a;
187 $name =~ s/\W/_/ag;
188
189 $arg = "const char * const $name";
190 die_at_end 'm flag required for "literal" argument'
191 unless $flags =~ /m/;
192 }
193 elsif ( $args_assert_line
194 && $arg =~ /\*/
195 && $arg !~ /\b(NN|NULLOK)\b/ )
99eff296 196 {
9824c081
MS
197 warn "$func: $arg needs NN or NULLOK\n";
198 ++$unflagged_pointers;
199 }
200 my $nn = ( $arg =~ s/\s*\bNN\b\s+// );
201 push( @nonnull, $n ) if $nn;
202
203 my $nullok = ( $arg =~ s/\s*\bNULLOK\b\s+// ); # strip NULLOK with no effect
204
205 # Make sure each arg has at least a type and a var name.
206 # An arg of "int" is valid C, but want it to be "int foo".
207 my $temp_arg = $arg;
208 $temp_arg =~ s/\*//g;
209 $temp_arg =~ s/\s*\bstruct\b\s*/ /g;
210 if ( ($temp_arg ne "...")
211 && ($temp_arg !~ /\w+\s+(\w+)(?:\[\d+\])?\s*$/) ) {
212 die_at_end "$func: $arg ($n) doesn't have a name\n";
213 }
214 if (defined $1 && $nn && !($commented_out && !$binarycompat)) {
215 push @names_of_nn, $1;
216 }
217 }
218 $ret .= join ", ", @args;
219 }
220 else {
221 $ret .= "void" if !$has_context;
222 }
21553840 223 $ret .= " _pDEPTH" if $has_depth;
9824c081
MS
224 $ret .= ")";
225 my @attrs;
226 if ( $flags =~ /r/ ) {
227 push @attrs, "__attribute__noreturn__";
228 }
229 if ( $flags =~ /D/ ) {
230 push @attrs, "__attribute__deprecated__";
231 }
232 if ( $is_malloc ) {
233 push @attrs, "__attribute__malloc__";
234 }
235 if ( !$can_ignore ) {
236 push @attrs, "__attribute__warn_unused_result__";
237 }
238 if ( $flags =~ /P/ ) {
239 push @attrs, "__attribute__pure__";
240 }
241 if ( $flags =~ /I/ ) {
242 push @attrs, "__attribute__always_inline__";
243 }
0351a629
TK
244 # roughly the inverse of the rules used in makedef.pl
245 if ( $flags !~ /[ACeIimSX]/ ) {
246 push @attrs, '__attribute__visibility__("hidden")'
247 }
9824c081
MS
248 if( $flags =~ /f/ ) {
249 my $prefix = $has_context ? 'pTHX_' : '';
c553bad5 250 my ($argc, $pat);
9824c081 251 if ($args[-1] eq '...') {
c553bad5
PE
252 $argc = scalar @args;
253 $pat = $argc - 1;
254 $argc = $prefix . $argc;
9824c081
MS
255 }
256 else {
257 # don't check args, and guess which arg is the pattern
258 # (one of 'fmt', 'pat', 'f'),
c553bad5 259 $argc = 0;
9824c081
MS
260 my @fmts = grep $args[$_] =~ /\b(f|pat|fmt)$/, 0..$#args;
261 if (@fmts != 1) {
262 die "embed.pl: '$plain_func': can't determine pattern arg\n";
263 }
264 $pat = $fmts[0] + 1;
265 }
266 my $macro = grep($_ == $pat, @nonnull)
267 ? '__attribute__format__'
268 : '__attribute__format__null_ok__';
269 if ($plain_func =~ /strftime/) {
270 push @attrs, sprintf "%s(__strftime__,%s1,0)", $macro, $prefix;
271 }
272 else {
273 push @attrs, sprintf "%s(__printf__,%s%d,%s)", $macro,
c553bad5 274 $prefix, $pat, $argc;
9824c081
MS
275 }
276 }
277 elsif ((grep { $_ eq '...' } @args) && $flags !~ /F/) {
278 die_at_end "$plain_func: Function with '...' arguments must have"
279 . " f or F flag";
280 }
281 if ( @attrs ) {
282 $ret .= "\n";
283 $ret .= join( "\n", map { "\t\t\t$_" } @attrs );
284 }
285 $ret .= ";";
286 $ret = "/* $ret */" if $commented_out;
287
288 $ret .= "\n#define PERL_ARGS_ASSERT_\U$plain_func\E"
289 if $args_assert_line || @names_of_nn;
290 $ret .= "\t\\\n\t" . join '; ', map "assert($_)", @names_of_nn
291 if @names_of_nn;
292
293 $ret = "#ifndef PERL_NO_INLINE_FUNCTIONS\n$ret\n#endif" if $static_inline;
294 $ret = "#ifndef NO_MATHOMS\n$ret\n#endif" if $binarycompat;
295 $ret .= @attrs ? "\n\n" : "\n";
296
297 print $pr $ret;
cea2e8a9 298 }
9516dc40 299
897d3989
NC
300 print $pr <<'EOF';
301#ifdef PERL_CORE
302# include "pp_proto.h"
303#endif
304END_EXTERN_C
897d3989 305EOF
9516dc40 306
eeec122d 307 read_only_bottom_close_and_rename($pr) if ! $error_count;
cea2e8a9
GS
308}
309
eeec122d 310die_at_end "$unflagged_pointers pointer arguments to clean up\n" if $unflagged_pointers;
cea2e8a9 311
adf34b4b
NC
312sub readvars {
313 my ($file, $pre) = @_;
d4cce5f1 314 local (*FILE, $_);
adf34b4b 315 my %seen;
1ae6ead9 316 open(FILE, '<', $file)
9824c081 317 or die "embed.pl: Can't open $file: $!\n";
d4cce5f1 318 while (<FILE>) {
9824c081
MS
319 s/[ \t]*#.*//; # Delete comments.
320 if (/PERLVARA?I?C?\($pre,\s*(\w+)/) {
321 die_at_end "duplicate symbol $1 while processing $file line $.\n"
322 if $seen{$1}++;
323 }
d4cce5f1
NIS
324 }
325 close(FILE);
adf34b4b 326 return sort keys %seen;
d4cce5f1
NIS
327}
328
adf34b4b
NC
329my @intrp = readvars 'intrpvar.h','I';
330my @globvar = readvars 'perlvars.h','G';
d4cce5f1 331
125218eb
NC
332sub hide {
333 my ($from, $to, $indent) = @_;
334 $indent = '' unless defined $indent;
335 my $t = int(length("$indent$from") / 8);
336 "#${indent}define $from" . "\t" x ($t < 3 ? 3 - $t : 1) . "$to\n";
5f05dabc 337}
c6af7a1a 338
d4cce5f1
NIS
339sub multon ($$$) {
340 my ($sym,$pre,$ptr) = @_;
3280af22 341 hide("PL_$sym", "($ptr$pre$sym)");
5f05dabc 342}
54aff467 343
5f8dc073 344my $em = open_print_header('embed.h');
e50aee73 345
5f8dc073 346print $em <<'END';
e50aee73
AD
347/* (Doing namespace management portably in C is really gross.) */
348
d51482e4
JH
349/* By defining PERL_NO_SHORT_NAMES (not done by default) the short forms
350 * (like warn instead of Perl_warn) for the API are not defined.
e8581bc2
KW
351 * Not defining the short forms is a good thing for cleaner embedding.
352 * BEWARE that a bunch of macros don't have long names, so either must be
353 * added or don't use them if you define this symbol */
d51482e4
JH
354
355#ifndef PERL_NO_SHORT_NAMES
820c3be9 356
22c35a8c 357/* Hide global symbols */
5f05dabc 358
e50aee73
AD
359END
360
cea2e8a9
GS
361my @az = ('a'..'z');
362
e8a67806
NC
363sub embed_h {
364 my ($guard, $funcs) = @_;
365 print $em "$guard\n" if $guard;
366
2a4d8072 367 my $lines;
e8a67806 368 foreach (@$funcs) {
9824c081
MS
369 if (@$_ == 1) {
370 my $cond = $_->[0];
371 # Indent the conditionals if we are wrapped in an #if/#endif pair.
372 $cond =~ s/#(.*)/# $1/ if $guard;
373 $lines .= "$cond\n";
374 next;
375 }
376 my $ret = "";
377 my ($flags,$retval,$func,@args) = @$_;
378 unless ($flags =~ /[omM]/) {
c553bad5 379 my $argc = scalar @args;
9824c081
MS
380 if ($flags =~ /T/) {
381 my $full_name = full_name($func, $flags);
382 next if $full_name eq $func; # Don't output a no-op.
383 $ret = hide($func, $full_name);
384 }
9824c081 385 else {
13e5ba49
PE
386 my $use_va_list = $argc && $args[-1] =~ /\.\.\./;
387
388 if($use_va_list) {
389 # CPP has trouble with empty __VA_ARGS__ and comma joining,
390 # so we'll have to eat an extra params here.
391 if($argc < 2) {
392 die "Cannot use ... as the only parameter to a macro ($func)\n";
393 }
394 $argc -= 2;
395 }
396
397 my $paramlist = join(",", @az[0..$argc-1],
398 $use_va_list ? ("...") : ());
399 my $replacelist = join(",", @az[0..$argc-1],
400 $use_va_list ? ("__VA_ARGS__") : ());
401
402 $ret = "#define $func($paramlist)";
9824c081
MS
403 my $t = int(length($ret) / 8);
404 $ret .= "\t" x ($t < 4 ? 4 - $t : 1);
405 $ret .= full_name($func, $flags) . "(aTHX";
13e5ba49
PE
406 $ret .= "_ " if $replacelist;
407 $ret .= $replacelist;
21553840 408 if ($flags =~ /W/) {
13e5ba49 409 if ($replacelist) {
21553840
YO
410 $ret .= " _aDEPTH";
411 } else {
412 die "Can't use W without other args (currently)";
413 }
414 }
415 $ret .= ")\n";
13e5ba49
PE
416
417 if($use_va_list) {
418 # Make them available to !MULTIPLICITY or PERL_CORE
419 $ret = "#if !defined(MULTIPLICITY) || defined(PERL_CORE)\n" .
420 $ret .
421 "#endif\n";
422 }
9824c081
MS
423 }
424 $ret = "#ifndef NO_MATHOMS\n$ret#endif\n" if $flags =~ /b/;
425 }
426 $lines .= $ret;
cea2e8a9 427 }
2a4d8072
NC
428 # Prune empty #if/#endif pairs.
429 while ($lines =~ s/#\s*if[^\n]+\n#\s*endif\n//) {
430 }
b2e549c0 431 # Merge adjacent blocks.
6e512bc2 432 while ($lines =~ s/(#ifndef MULTIPLICITY
b2e549c0
NC
433[^\n]+
434)#endif
6e512bc2 435#ifndef MULTIPLICITY
b2e549c0
NC
436/$1/) {
437 }
438
2a4d8072 439 print $em $lines;
e8a67806 440 print $em "#endif\n" if $guard;
da4ddda1
NC
441}
442
5ccbf88e
NC
443embed_h('', $api);
444embed_h('#if defined(PERL_CORE) || defined(PERL_EXT)', $ext);
445embed_h('#ifdef PERL_CORE', $core);
e8a67806 446
424a4936 447print $em <<'END';
e50aee73 448
d51482e4 449#endif /* #ifndef PERL_NO_SHORT_NAMES */
35209cc8 450
cea2e8a9
GS
451/* Compatibility stubs. Compile extensions with -DPERL_NOCOMPAT to
452 disable them.
453 */
454
538feb02 455#if !defined(PERL_CORE)
5bc28da9 456# define sv_setptrobj(rv,ptr,name) sv_setref_iv(rv,name,PTR2IV(ptr))
a0714e2c 457# define sv_setptrref(rv,ptr) sv_setref_iv(rv,NULL,PTR2IV(ptr))
538feb02 458#endif
cea2e8a9 459
08e5223a 460#if !defined(PERL_CORE) && !defined(PERL_NOCOMPAT)
cea2e8a9
GS
461
462/* Compatibility for various misnamed functions. All functions
463 in the API that begin with "perl_" (not "Perl_") take an explicit
464 interpreter context pointer.
465 The following are not like that, but since they had a "perl_"
466 prefix in previous versions, we provide compatibility macros.
467 */
65cec589 468# define perl_atexit(a,b) call_atexit(a,b)
7b53c8ee
NC
469END
470
3a54c8e7
NC
471foreach (@$embed) {
472 my ($flags, $retval, $func, @args) = @$_;
473 next unless $func;
474 next unless $flags =~ /O/;
7b53c8ee
NC
475
476 my $alist = join ",", @az[0..$#args];
477 my $ret = "# define perl_$func($alist)";
478 my $t = (length $ret) >> 3;
479 $ret .= "\t" x ($t < 5 ? 5 - $t : 1);
3a54c8e7
NC
480 print $em "$ret$func($alist)\n";
481}
7b53c8ee 482
eacd26c2
NC
483my @nocontext;
484{
485 my (%has_va, %has_nocontext);
5ccbf88e 486 foreach (@$embed) {
9824c081
MS
487 next unless @$_ > 1;
488 ++$has_va{$_->[2]} if $_->[-1] =~ /\.\.\./;
489 ++$has_nocontext{$1} if $_->[2] =~ /(.*)_nocontext/;
eacd26c2
NC
490 }
491
492 @nocontext = sort grep {
9824c081
MS
493 $has_nocontext{$_}
494 && !/printf/ # Not clear to me why these are skipped but they are.
eacd26c2
NC
495 } keys %has_va;
496}
497
7b53c8ee 498print $em <<'END';
cea2e8a9
GS
499
500/* varargs functions can't be handled with CPP macros. :-(
501 This provides a set of compatibility functions that don't take
502 an extra argument but grab the context pointer using the macro
503 dTHX.
504 */
6e512bc2 505#if defined(MULTIPLICITY) && !defined(PERL_NO_SHORT_NAMES)
125218eb
NC
506END
507
eacd26c2 508foreach (@nocontext) {
125218eb
NC
509 print $em hide($_, "Perl_${_}_nocontext", " ");
510}
511
512print $em <<'END';
cea2e8a9
GS
513#endif
514
515#endif /* !defined(PERL_CORE) && !defined(PERL_NOCOMPAT) */
516
6e512bc2 517#if !defined(MULTIPLICITY)
cea2e8a9 518/* undefined symbols, point them back at the usual ones */
125218eb
NC
519END
520
eacd26c2 521foreach (@nocontext) {
125218eb
NC
522 print $em hide("Perl_${_}_nocontext", "Perl_$_", " ");
523}
524
525print $em <<'END';
cea2e8a9 526#endif
d4cce5f1
NIS
527END
528
eeec122d 529read_only_bottom_close_and_rename($em) if ! $error_count;
d4cce5f1 530
5f8dc073 531$em = open_print_header('embedvar.h');
d4cce5f1 532
5f8dc073 533print $em <<'END';
54aff467 534#if defined(MULTIPLICITY)
6e512bc2 535# define vTHX aTHX
e50aee73
AD
536END
537
adf34b4b
NC
538my $sym;
539
540for $sym (@intrp) {
1a904fc8 541 if ($sym eq 'sawampersand') {
9824c081 542 print $em "#ifndef PL_sawampersand\n";
1a904fc8 543 }
424a4936 544 print $em multon($sym,'I','vTHX->');
1a904fc8 545 if ($sym eq 'sawampersand') {
9824c081 546 print $em "#endif\n";
1a904fc8 547 }
d4cce5f1
NIS
548}
549
424a4936 550print $em <<'END';
d4cce5f1 551
54aff467 552#endif /* MULTIPLICITY */
84fee439
NIS
553END
554
eeec122d 555read_only_bottom_close_and_rename($em) if ! $error_count;
c6af7a1a 556
eeec122d 557die "$error_count errors found" if $error_count;
acfe0abc 558
1b6737cc 559# ex: set ts=8 sts=4 sw=4 noet: