Re: [PATCH] reentr.h changes so threaded Perl's compile on OpenBSD 3.7
[p5sagit/p5-mst-13.2.git] / reentr.pl
CommitLineData
10bc17b6 1#!/usr/bin/perl -w
2
3#
4# Generate the reentr.c and reentr.h,
5# and optionally also the relevant metaconfig units (-U option).
6#
7
8use strict;
9use Getopt::Std;
10my %opts;
11getopts('U', \%opts);
12
13my %map = (
14 V => "void",
15 A => "char*", # as an input argument
16 B => "char*", # as an output argument
17 C => "const char*", # as a read-only input argument
18 I => "int",
19 L => "long",
20 W => "size_t",
21 H => "FILE**",
22 E => "int*",
23 );
24
25# (See the definitions after __DATA__.)
26# In func|inc|type|... a "S" means "type*", and a "R" means "type**".
27# (The "types" are often structs, such as "struct passwd".)
28#
29# After the prototypes one can have |X=...|Y=... to define more types.
30# A commonly used extra type is to define D to be equal to "type_data",
31# for example "struct_hostent_data to" go with "struct hostent".
32#
33# Example #1: I_XSBWR means int func_r(X, type, char*, size_t, type**)
34# Example #2: S_SBIE means type func_r(type, char*, int, int*)
35# Example #3: S_CBI means type func_r(const char*, char*, int)
36
37
38die "reentr.h: $!" unless open(H, ">reentr.h");
39select H;
40print <<EOF;
41/*
42 * reentr.h
43 *
23e2b7a9 44 * Copyright (C) 2002, 2003, 2005 by Larry Wall and others
10bc17b6 45 *
46 * You may distribute under the terms of either the GNU General Public
47 * License or the Artistic License, as specified in the README file.
48 *
49 * !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
61296642 50 * This file is built by reentr.pl from data in reentr.pl.
10bc17b6 51 */
52
53#ifndef REENTR_H
54#define REENTR_H
55
56#ifdef USE_REENTRANT_API
57
58/* Deprecations: some platforms have the said reentrant interfaces
59 * but they are declared obsolete and are not to be used. Often this
60 * means that the platform has threadsafed the interfaces (hopefully).
61 * All this is OS version dependent, so we are of course fooling ourselves.
62 * If you know of more deprecations on some platforms, please add your own. */
63
64#ifdef __hpux
65# undef HAS_CRYPT_R
66# undef HAS_DRAND48_R
efa45b01 67# undef HAS_ENDGRENT_R
68# undef HAS_ENDPWENT_R
10bc17b6 69# undef HAS_GETGRENT_R
70# undef HAS_GETPWENT_R
71# undef HAS_SETLOCALE_R
72# undef HAS_SRAND48_R
73# undef HAS_STRERROR_R
74# define NETDB_R_OBSOLETE
75#endif
76
77#if defined(__osf__) && defined(__alpha) /* Tru64 aka Digital UNIX */
78# undef HAS_CRYPT_R
79# undef HAS_STRERROR_R
80# define NETDB_R_OBSOLETE
81#endif
82
23e2b7a9 83/*
84 * As of OpenBSD 3.7, reentrant functions are now working, they just are
85 * incompatible with everyone else. To make OpenBSD happy, we have to
86 * memzero out certain structures before calling the functions.
87 */
88#if defined(__OpenBSD__)
89# define REENTR_MEMZERO(a,b) memzero(a,b),
90#else
91# define REENTR_MEMZERO(a,b)
92#endif
93
10bc17b6 94#ifdef NETDB_R_OBSOLETE
95# undef HAS_ENDHOSTENT_R
96# undef HAS_ENDNETENT_R
97# undef HAS_ENDPROTOENT_R
98# undef HAS_ENDSERVENT_R
99# undef HAS_GETHOSTBYADDR_R
100# undef HAS_GETHOSTBYNAME_R
101# undef HAS_GETHOSTENT_R
102# undef HAS_GETNETBYADDR_R
103# undef HAS_GETNETBYNAME_R
104# undef HAS_GETNETENT_R
105# undef HAS_GETPROTOBYNAME_R
106# undef HAS_GETPROTOBYNUMBER_R
107# undef HAS_GETPROTOENT_R
108# undef HAS_GETSERVBYNAME_R
109# undef HAS_GETSERVBYPORT_R
110# undef HAS_GETSERVENT_R
111# undef HAS_SETHOSTENT_R
112# undef HAS_SETNETENT_R
113# undef HAS_SETPROTOENT_R
114# undef HAS_SETSERVENT_R
115#endif
116
117#ifdef I_PWD
118# include <pwd.h>
119#endif
120#ifdef I_GRP
121# include <grp.h>
122#endif
123#ifdef I_NETDB
124# include <netdb.h>
125#endif
126#ifdef I_STDLIB
127# include <stdlib.h> /* drand48_data */
128#endif
129#ifdef I_CRYPT
130# ifdef I_CRYPT
131# include <crypt.h>
132# endif
133#endif
134#ifdef HAS_GETSPNAM_R
135# ifdef I_SHADOW
136# include <shadow.h>
137# endif
138#endif
139
140EOF
141
aa418cf1 142my %seenh; # the different prototypes signatures for this function
143my %seena; # the different prototypes signatures for this function in order
144my @seenf; # all the seen functions
145my %seenp; # the different prototype signatures for all functions
146my %seent; # the return type of this function
147my %seens; # the type of this function's "S"
148my %seend; # the type of this function's "D"
a845a0d4 149my %seenm; # all the types
aa418cf1 150my %seenu; # the length of the argument list of this function
151
152while (<DATA>) { # Read in the protypes.
10bc17b6 153 next if /^\s+$/;
154 chomp;
aa418cf1 155 my ($func, $hdr, $type, @p) = split(/\s*\|\s*/, $_, -1);
10bc17b6 156 my $u;
aa418cf1 157 # Split off the real function name and the argument list.
158 ($func, $u) = split(' ', $func);
159 $seenu{$func} = defined $u ? length $u : 0;
160 my $FUNC = uc $func; # for output.
161 push @seenf, $func;
10bc17b6 162 my %m = %map;
aa418cf1 163 if ($type) {
164 $m{S} = "$type*";
165 $m{R} = "$type**";
10bc17b6 166 }
aa418cf1 167
168 # Set any special mapping variables (like X=x_t)
10bc17b6 169 if (@p) {
170 while ($p[-1] =~ /=/) {
171 my ($k, $v) = ($p[-1] =~ /^([A-Za-z])\s*=\s*(.*)/);
172 $m{$k} = $v;
173 pop @p;
174 }
175 }
aa418cf1 176
177 # If given the -U option open up the metaconfig unit for this function.
178 if ($opts{U} && open(U, ">d_${func}_r.U")) {
10bc17b6 179 select U;
180 }
aa418cf1 181
d63eadf0 182 if ($opts{U}) {
aa418cf1 183 # The metaconfig units needs prerequisite dependencies.
184 my $prereqs = '';
185 my $prereqh = '';
186 my $prereqsh = '';
187 if ($hdr ne 'stdio') { # There's no i_stdio.
188 $prereqs = "i_$hdr";
189 $prereqh = "$hdr.h";
190 $prereqsh = "\$$prereqs $prereqh";
191 }
1fdb6f84 192 my @prereq = qw(Inlibc Protochk Hasproto i_systypes usethreads);
193 push @prereq, $prereqs;
194 my $hdrs = "\$i_systypes sys/types.h define stdio.h $prereqsh";
aa418cf1 195 if ($hdr eq 'time') {
1fdb6f84 196 $hdrs .= " \$i_systime sys/time.h";
197 push @prereq, 'i_systime';
198 }
aa418cf1 199 # Output the metaconfig unit header.
d63eadf0 200 print <<EOF;
aa418cf1 201?RCS: \$Id: d_${func}_r.U,v $
10bc17b6 202?RCS:
a845a0d4 203?RCS: Copyright (c) 2002,2003 Jarkko Hietaniemi
10bc17b6 204?RCS:
205?RCS: You may distribute under the terms of either the GNU General Public
206?RCS: License or the Artistic License, as specified in the README file.
207?RCS:
208?RCS: Generated by the reentr.pl from the Perl 5.8 distribution.
209?RCS:
aa418cf1 210?MAKE:d_${func}_r ${func}_r_proto: @prereq
10bc17b6 211?MAKE: -pick add \$@ %<
aa418cf1 212?S:d_${func}_r:
213?S: This variable conditionally defines the HAS_${FUNC}_R symbol,
214?S: which indicates to the C program that the ${func}_r()
10bc17b6 215?S: routine is available.
216?S:.
aa418cf1 217?S:${func}_r_proto:
218?S: This variable encodes the prototype of ${func}_r.
39183afa 219?S: It is zero if d_${func}_r is undef, and one of the
220?S: REENTRANT_PROTO_T_ABC macros of reentr.h if d_${func}_r
221?S: is defined.
10bc17b6 222?S:.
aa418cf1 223?C:HAS_${FUNC}_R:
224?C: This symbol, if defined, indicates that the ${func}_r routine
225?C: is available to ${func} re-entrantly.
10bc17b6 226?C:.
aa418cf1 227?C:${FUNC}_R_PROTO:
228?C: This symbol encodes the prototype of ${func}_r.
39183afa 229?C: It is zero if d_${func}_r is undef, and one of the
230?C: REENTRANT_PROTO_T_ABC macros of reentr.h if d_${func}_r
231?C: is defined.
10bc17b6 232?C:.
aa418cf1 233?H:#\$d_${func}_r HAS_${FUNC}_R /**/
234?H:#define ${FUNC}_R_PROTO \$${func}_r_proto /**/
10bc17b6 235?H:.
aa418cf1 236?T:try hdrs d_${func}_r_proto
237?LINT:set d_${func}_r
238?LINT:set ${func}_r_proto
239: see if ${func}_r exists
240set ${func}_r d_${func}_r
10bc17b6 241eval \$inlibc
aa418cf1 242case "\$d_${func}_r" in
10bc17b6 243"\$define")
d63eadf0 244EOF
d63eadf0 245 print <<EOF;
246 hdrs="$hdrs"
aa418cf1 247 case "\$d_${func}_r_proto:\$usethreads" in
248 ":define") d_${func}_r_proto=define
249 set d_${func}_r_proto ${func}_r \$hdrs
a48ec845 250 eval \$hasproto ;;
251 *) ;;
252 esac
aa418cf1 253 case "\$d_${func}_r_proto" in
a48ec845 254 define)
10bc17b6 255EOF
d63eadf0 256 }
257 for my $p (@p) {
258 my ($r, $a) = ($p =~ /^(.)_(.+)/);
259 my $v = join(", ", map { $m{$_} } split '', $a);
260 if ($opts{U}) {
261 print <<EOF ;
aa418cf1 262 case "\$${func}_r_proto" in
263 ''|0) try='$m{$r} ${func}_r($v);'
264 ./protochk "extern \$try" \$hdrs && ${func}_r_proto=$p ;;
10bc17b6 265 esac
266EOF
d63eadf0 267 }
aa418cf1 268 $seenh{$func}->{$p}++;
269 push @{$seena{$func}}, $p;
d63eadf0 270 $seenp{$p}++;
aa418cf1 271 $seent{$func} = $type;
272 $seens{$func} = $m{S};
273 $seend{$func} = $m{D};
a845a0d4 274 $seenm{$func} = \%m;
d63eadf0 275 }
276 if ($opts{U}) {
277 print <<EOF;
aa418cf1 278 case "\$${func}_r_proto" in
279 ''|0) d_${func}_r=undef
280 ${func}_r_proto=0
281 echo "Disabling ${func}_r, cannot determine prototype." >&4 ;;
282 * ) case "\$${func}_r_proto" in
10bc17b6 283 REENTRANT_PROTO*) ;;
aa418cf1 284 *) ${func}_r_proto="REENTRANT_PROTO_\$${func}_r_proto" ;;
10bc17b6 285 esac
286 echo "Prototype: \$try" ;;
287 esac
288 ;;
c18e646a 289 *) case "\$usethreads" in
aa418cf1 290 define) echo "${func}_r has no prototype, not using it." >&4 ;;
c18e646a 291 esac
aa418cf1 292 d_${func}_r=undef
293 ${func}_r_proto=0
c18e646a 294 ;;
a48ec845 295 esac
296 ;;
aa418cf1 297*) ${func}_r_proto=0
10bc17b6 298 ;;
299esac
300
301EOF
302 close(U);
303 }
304}
305
306close DATA;
307
aa418cf1 308# Prepare to continue writing the reentr.h.
309
10bc17b6 310select H;
311
312{
aa418cf1 313 # Write out all the known prototype signatures.
10bc17b6 314 my $i = 1;
315 for my $p (sort keys %seenp) {
316 print "#define REENTRANT_PROTO_${p} ${i}\n";
317 $i++;
318 }
319}
320
aa418cf1 321my @struct; # REENTR struct members
322my @size; # struct member buffer size initialization code
323my @init; # struct member buffer initialization (malloc) code
324my @free; # struct member buffer release (free) code
325my @wrap; # the wrapper (foo(a) -> foo_r(a,...)) cpp code
326my @define; # defines for optional features
327
10bc17b6 328sub ifprotomatch {
aa418cf1 329 my $FUNC = shift;
330 join " || ", map { "${FUNC}_R_PROTO == REENTRANT_PROTO_$_" } @_;
10bc17b6 331}
332
10bc17b6 333sub pushssif {
334 push @struct, @_;
335 push @size, @_;
336 push @init, @_;
337 push @free, @_;
338}
339
340sub pushinitfree {
aa418cf1 341 my $func = shift;
10bc17b6 342 push @init, <<EOF;
aa418cf1 343 New(31338, PL_reentrant_buffer->_${func}_buffer, PL_reentrant_buffer->_${func}_size, char);
10bc17b6 344EOF
345 push @free, <<EOF;
aa418cf1 346 Safefree(PL_reentrant_buffer->_${func}_buffer);
10bc17b6 347EOF
348}
349
350sub define {
351 my ($n, $p, @F) = @_;
352 my @H;
353 my $H = uc $F[0];
354 push @define, <<EOF;
355/* The @F using \L$n? */
356
357EOF
aa418cf1 358 my $GENFUNC;
359 for my $func (@F) {
360 my $FUNC = uc $func;
361 my $HAS = "${FUNC}_R_HAS_$n";
362 push @H, $HAS;
363 my @h = grep { /$p/ } @{$seena{$func}};
364 unless (defined $GENFUNC) {
365 $GENFUNC = $FUNC;
366 $GENFUNC =~ s/^GET//;
f7937171 367 }
10bc17b6 368 if (@h) {
aa418cf1 369 push @define, "#if defined(HAS_${FUNC}_R) && (" . join(" || ", map { "${FUNC}_R_PROTO == REENTRANT_PROTO_$_" } @h) . ")\n";
10bc17b6 370
371 push @define, <<EOF;
aa418cf1 372# define $HAS
10bc17b6 373#else
aa418cf1 374# undef $HAS
10bc17b6 375#endif
376EOF
377 }
378 }
0891a229 379 return if @F == 1;
10bc17b6 380 push @define, <<EOF;
381
382/* Any of the @F using \L$n? */
383
384EOF
385 push @define, "#if (" . join(" || ", map { "defined($_)" } @H) . ")\n";
386 push @define, <<EOF;
aa418cf1 387# define USE_${GENFUNC}_$n
10bc17b6 388#else
aa418cf1 389# undef USE_${GENFUNC}_$n
10bc17b6 390#endif
391
392EOF
393}
394
edd309b7 395define('BUFFER', 'B',
396 qw(getgrent getgrgid getgrnam));
397
10bc17b6 398define('PTR', 'R',
399 qw(getgrent getgrgid getgrnam));
400define('PTR', 'R',
401 qw(getpwent getpwnam getpwuid));
402define('PTR', 'R',
403 qw(getspent getspnam));
404
405define('FPTR', 'H',
f7937171 406 qw(getgrent getgrgid getgrnam setgrent endgrent));
10bc17b6 407define('FPTR', 'H',
f7937171 408 qw(getpwent getpwnam getpwuid setpwent endpwent));
10bc17b6 409
edd309b7 410define('BUFFER', 'B',
411 qw(getpwent getpwgid getpwnam));
412
10bc17b6 413define('PTR', 'R',
414 qw(gethostent gethostbyaddr gethostbyname));
415define('PTR', 'R',
416 qw(getnetent getnetbyaddr getnetbyname));
417define('PTR', 'R',
418 qw(getprotoent getprotobyname getprotobynumber));
419define('PTR', 'R',
420 qw(getservent getservbyname getservbyport));
421
edd309b7 422define('BUFFER', 'B',
423 qw(gethostent gethostbyaddr gethostbyname));
424define('BUFFER', 'B',
425 qw(getnetent getnetbyaddr getnetbyname));
426define('BUFFER', 'B',
427 qw(getprotoent getprotobyname getprotobynumber));
428define('BUFFER', 'B',
429 qw(getservent getservbyname getservbyport));
430
10bc17b6 431define('ERRNO', 'E',
432 qw(gethostent gethostbyaddr gethostbyname));
433define('ERRNO', 'E',
434 qw(getnetent getnetbyaddr getnetbyname));
435
aa418cf1 436# The following loop accumulates the "ssif" (struct, size, init, free)
437# sections that declare the struct members (in reentr.h), and the buffer
438# size initialization, buffer initialization (malloc), and buffer
439# release (free) code (in reentr.c).
440#
441# The loop also contains a lot of intrinsic logic about groups of
442# functions (since functions of certain kind operate the same way).
443
444for my $func (@seenf) {
445 my $FUNC = uc $func;
446 my $ifdef = "#ifdef HAS_${FUNC}_R\n";
447 my $endif = "#endif /* HAS_${FUNC}_R */\n";
448 if (exists $seena{$func}) {
449 my @p = @{$seena{$func}};
450 if ($func =~ /^(asctime|ctime|getlogin|setlocale|strerror|ttyname)$/) {
10bc17b6 451 pushssif $ifdef;
452 push @struct, <<EOF;
aa418cf1 453 char* _${func}_buffer;
454 size_t _${func}_size;
10bc17b6 455EOF
456 push @size, <<EOF;
aa418cf1 457 PL_reentrant_buffer->_${func}_size = REENTRANTSMALLSIZE;
10bc17b6 458EOF
aa418cf1 459 pushinitfree $func;
10bc17b6 460 pushssif $endif;
461 }
aa418cf1 462 elsif ($func =~ /^(crypt)$/) {
10bc17b6 463 pushssif $ifdef;
464 push @struct, <<EOF;
b430fd04 465#if CRYPT_R_PROTO == REENTRANT_PROTO_B_CCD
aa418cf1 466 $seend{$func} _${func}_data;
b430fd04 467#else
05404ffe 468 $seent{$func} *_${func}_struct_buffer;
b430fd04 469#endif
10bc17b6 470EOF
b430fd04 471 push @init, <<EOF;
05404ffe 472#if CRYPT_R_PROTO != REENTRANT_PROTO_B_CCD
473 PL_reentrant_buffer->_${func}_struct_buffer = 0;
474#endif
475EOF
476 push @free, <<EOF;
477#if CRYPT_R_PROTO != REENTRANT_PROTO_B_CCD
478 Safefree(PL_reentrant_buffer->_${func}_struct_buffer);
10bc17b6 479#endif
480EOF
b430fd04 481 pushssif $endif;
482 }
5cb13b8d 483 elsif ($func =~ /^(drand48|gmtime|localtime|random|srandom)$/) {
b430fd04 484 pushssif $ifdef;
485 push @struct, <<EOF;
aa418cf1 486 $seent{$func} _${func}_struct;
b430fd04 487EOF
10bc17b6 488 if ($1 eq 'drand48') {
489 push @struct, <<EOF;
aa418cf1 490 double _${func}_double;
10bc17b6 491EOF
a845a0d4 492 } elsif ($1 eq 'random') {
493 push @struct, <<EOF;
b3b3b51f 494# if RANDOM_R_PROTO == REENTRANT_PROTO_I_iS
a845a0d4 495 int _${func}_retval;
496# endif
b3b3b51f 497# if RANDOM_R_PROTO == REENTRANT_PROTO_I_lS
a845a0d4 498 long _${func}_retval;
499# endif
b3b3b51f 500# if RANDOM_R_PROTO == REENTRANT_PROTO_I_St
a845a0d4 501 int32_t _${func}_retval;
502# endif
503EOF
10bc17b6 504 }
505 pushssif $endif;
506 }
aa418cf1 507 elsif ($func =~ /^(getgrnam|getpwnam|getspnam)$/) {
10bc17b6 508 pushssif $ifdef;
aa418cf1 509 # 'genfunc' can be read either as 'generic' or 'genre',
510 # it represents a group of functions.
511 my $genfunc = $func;
512 $genfunc =~ s/nam/ent/g;
513 $genfunc =~ s/^get//;
514 my $GENFUNC = uc $genfunc;
10bc17b6 515 push @struct, <<EOF;
aa418cf1 516 $seent{$func} _${genfunc}_struct;
517 char* _${genfunc}_buffer;
518 size_t _${genfunc}_size;
10bc17b6 519EOF
520 push @struct, <<EOF;
aa418cf1 521# ifdef USE_${GENFUNC}_PTR
522 $seent{$func}* _${genfunc}_ptr;
10bc17b6 523# endif
524EOF
0de8cad8 525 push @struct, <<EOF;
aa418cf1 526# ifdef USE_${GENFUNC}_FPTR
527 FILE* _${genfunc}_fptr;
10bc17b6 528# endif
529EOF
0de8cad8 530 push @init, <<EOF;
aa418cf1 531# ifdef USE_${GENFUNC}_FPTR
532 PL_reentrant_buffer->_${genfunc}_fptr = NULL;
10bc17b6 533# endif
534EOF
0de8cad8 535 my $sc = $genfunc eq 'grent' ?
10bc17b6 536 '_SC_GETGR_R_SIZE_MAX' : '_SC_GETPW_R_SIZE_MAX';
0de8cad8 537 my $sz = "_${genfunc}_size";
538 push @size, <<EOF;
10bc17b6 539# if defined(HAS_SYSCONF) && defined($sc) && !defined(__GLIBC__)
0de8cad8 540 PL_reentrant_buffer->$sz = sysconf($sc);
e3410746 541 if (PL_reentrant_buffer->$sz == -1)
542 PL_reentrant_buffer->$sz = REENTRANTUSUALSIZE;
10bc17b6 543# else
544# if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
0de8cad8 545 PL_reentrant_buffer->$sz = SIABUFSIZ;
10bc17b6 546# else
547# ifdef __sgi
0de8cad8 548 PL_reentrant_buffer->$sz = BUFSIZ;
10bc17b6 549# else
0de8cad8 550 PL_reentrant_buffer->$sz = REENTRANTUSUALSIZE;
10bc17b6 551# endif
552# endif
553# endif
554EOF
aa418cf1 555 pushinitfree $genfunc;
10bc17b6 556 pushssif $endif;
557 }
aa418cf1 558 elsif ($func =~ /^(gethostbyname|getnetbyname|getservbyname|getprotobyname)$/) {
10bc17b6 559 pushssif $ifdef;
aa418cf1 560 my $genfunc = $func;
561 $genfunc =~ s/byname/ent/;
562 $genfunc =~ s/^get//;
563 my $GENFUNC = uc $genfunc;
564 my $D = ifprotomatch($FUNC, grep {/D/} @p);
565 my $d = $seend{$func};
31ee0cb7 566 $d =~ s/\*$//; # snip: we need need the base type.
10bc17b6 567 push @struct, <<EOF;
aa418cf1 568 $seent{$func} _${genfunc}_struct;
10bc17b6 569# if $D
aa418cf1 570 $d _${genfunc}_data;
10bc17b6 571# else
aa418cf1 572 char* _${genfunc}_buffer;
573 size_t _${genfunc}_size;
10bc17b6 574# endif
aa418cf1 575# ifdef USE_${GENFUNC}_PTR
576 $seent{$func}* _${genfunc}_ptr;
10bc17b6 577# endif
578EOF
579 push @struct, <<EOF;
aa418cf1 580# ifdef USE_${GENFUNC}_ERRNO
581 int _${genfunc}_errno;
10bc17b6 582# endif
583EOF
584 push @size, <<EOF;
585#if !($D)
aa418cf1 586 PL_reentrant_buffer->_${genfunc}_size = REENTRANTUSUALSIZE;
10bc17b6 587#endif
588EOF
589 push @init, <<EOF;
590#if !($D)
aa418cf1 591 New(31338, PL_reentrant_buffer->_${genfunc}_buffer, PL_reentrant_buffer->_${genfunc}_size, char);
10bc17b6 592#endif
593EOF
594 push @free, <<EOF;
595#if !($D)
aa418cf1 596 Safefree(PL_reentrant_buffer->_${genfunc}_buffer);
10bc17b6 597#endif
598EOF
599 pushssif $endif;
600 }
aa418cf1 601 elsif ($func =~ /^(readdir|readdir64)$/) {
10bc17b6 602 pushssif $ifdef;
aa418cf1 603 my $R = ifprotomatch($FUNC, grep {/R/} @p);
10bc17b6 604 push @struct, <<EOF;
aa418cf1 605 $seent{$func}* _${func}_struct;
606 size_t _${func}_size;
10bc17b6 607# if $R
aa418cf1 608 $seent{$func}* _${func}_ptr;
10bc17b6 609# endif
610EOF
611 push @size, <<EOF;
612 /* This is the size Solaris recommends.
613 * (though we go static, should use pathconf() instead) */
aa418cf1 614 PL_reentrant_buffer->_${func}_size = sizeof($seent{$func}) + MAXPATHLEN + 1;
10bc17b6 615EOF
616 push @init, <<EOF;
aa418cf1 617 PL_reentrant_buffer->_${func}_struct = ($seent{$func}*)safemalloc(PL_reentrant_buffer->_${func}_size);
10bc17b6 618EOF
619 push @free, <<EOF;
aa418cf1 620 Safefree(PL_reentrant_buffer->_${func}_struct);
10bc17b6 621EOF
622 pushssif $endif;
623 }
624
625 push @wrap, $ifdef;
626
10bc17b6 627 push @wrap, <<EOF;
aa418cf1 628# undef $func
10bc17b6 629EOF
aa418cf1 630
631 # Write out what we have learned.
632
10bc17b6 633 my @v = 'a'..'z';
aa418cf1 634 my $v = join(", ", @v[0..$seenu{$func}-1]);
10bc17b6 635 for my $p (@p) {
636 my ($r, $a) = split '_', $p;
637 my $test = $r eq 'I' ? ' == 0' : '';
638 my $true = 1;
aa418cf1 639 my $genfunc = $func;
640 if ($genfunc =~ /^(?:get|set|end)(pw|gr|host|net|proto|serv|sp)/) {
641 $genfunc = "${1}ent";
642 } elsif ($genfunc eq 'srand48') {
643 $genfunc = "drand48";
10bc17b6 644 }
645 my $b = $a;
646 my $w = '';
aa418cf1 647 substr($b, 0, $seenu{$func}) = '';
a845a0d4 648 if ($func =~ /^random$/) {
649 $true = "PL_reentrant_buffer->_random_retval";
650 } elsif ($b =~ /R/) {
aa418cf1 651 $true = "PL_reentrant_buffer->_${genfunc}_ptr";
652 } elsif ($b =~ /T/ && $func eq 'drand48') {
653 $true = "PL_reentrant_buffer->_${genfunc}_double";
10bc17b6 654 } elsif ($b =~ /S/) {
aa418cf1 655 if ($func =~ /^readdir/) {
656 $true = "PL_reentrant_buffer->_${genfunc}_struct";
10bc17b6 657 } else {
aa418cf1 658 $true = "&PL_reentrant_buffer->_${genfunc}_struct";
10bc17b6 659 }
660 } elsif ($b =~ /B/) {
aa418cf1 661 $true = "PL_reentrant_buffer->_${genfunc}_buffer";
10bc17b6 662 }
663 if (length $b) {
664 $w = join ", ",
665 map {
666 $_ eq 'R' ?
aa418cf1 667 "&PL_reentrant_buffer->_${genfunc}_ptr" :
10bc17b6 668 $_ eq 'E' ?
aa418cf1 669 "&PL_reentrant_buffer->_${genfunc}_errno" :
10bc17b6 670 $_ eq 'B' ?
aa418cf1 671 "PL_reentrant_buffer->_${genfunc}_buffer" :
10bc17b6 672 $_ =~ /^[WI]$/ ?
aa418cf1 673 "PL_reentrant_buffer->_${genfunc}_size" :
10bc17b6 674 $_ eq 'H' ?
aa418cf1 675 "&PL_reentrant_buffer->_${genfunc}_fptr" :
10bc17b6 676 $_ eq 'D' ?
aa418cf1 677 "&PL_reentrant_buffer->_${genfunc}_data" :
10bc17b6 678 $_ eq 'S' ?
05404ffe 679 ($func =~ /^readdir\d*$/ ?
aa418cf1 680 "PL_reentrant_buffer->_${genfunc}_struct" :
05404ffe 681 $func =~ /^crypt$/ ?
682 "PL_reentrant_buffer->_${genfunc}_struct_buffer" :
683 "&PL_reentrant_buffer->_${genfunc}_struct") :
aa418cf1 684 $_ eq 'T' && $func eq 'drand48' ?
685 "&PL_reentrant_buffer->_${genfunc}_double" :
a845a0d4 686 $_ =~ /^[ilt]$/ && $func eq 'random' ?
687 "&PL_reentrant_buffer->_random_retval" :
10bc17b6 688 $_
689 } split '', $b;
690 $w = ", $w" if length $v;
691 }
aa418cf1 692 my $call = "${func}_r($v$w)";
23e2b7a9 693
694 # Must make OpenBSD happy
695 my $memzero = '';
696 if($p =~ /D$/ &&
697 ($genfunc eq 'protoent' || $genfunc eq 'servent')) {
698 $memzero = 'REENTR_MEMZERO(&PL_reentrant_buffer->_' . $genfunc . '_data, sizeof(PL_reentrant_buffer->_' . $genfunc . '_data))';
699 }
10bc17b6 700 push @wrap, <<EOF;
aa418cf1 701# if !defined($func) && ${FUNC}_R_PROTO == REENTRANT_PROTO_$p
10bc17b6 702EOF
703 if ($r eq 'V' || $r eq 'B') {
704 push @wrap, <<EOF;
aa418cf1 705# define $func($v) $call
10bc17b6 706EOF
707 } else {
aa418cf1 708 if ($func =~ /^get/) {
edd309b7 709 my $rv = $v ? ", $v" : "";
0891a229 710 if ($r eq 'I') {
711 push @wrap, <<EOF;
23e2b7a9 712# define $func($v) ($memzero(PL_reentrant_retint = $call)$test ? $true : (((PL_reentrant_retint == ERANGE) || (errno == ERANGE)) ? ($seent{$func} *) Perl_reentrant_retry("$func"$rv) : 0))
0891a229 713EOF
714 } else {
715 push @wrap, <<EOF;
f6f0b69b 716# define $func($v) ($call$test ? $true : ((errno == ERANGE) ? ($seent{$func} *) Perl_reentrant_retry("$func"$rv) : 0))
10bc17b6 717EOF
0891a229 718 }
edd309b7 719 } else {
720 push @wrap, <<EOF;
aa418cf1 721# define $func($v) ($call$test ? $true : 0)
edd309b7 722EOF
723 }
10bc17b6 724 }
725 push @wrap, <<EOF;
726# endif
727EOF
728 }
729
730 push @wrap, $endif, "\n";
731 }
732}
733
734local $" = '';
735
736print <<EOF;
737
738/* Defines for indicating which special features are supported. */
739
740@define
741typedef struct {
742@struct
aa418cf1 743 int dummy; /* cannot have empty structs */
10bc17b6 744} REENTR;
745
746/* The wrappers. */
747
748@wrap
0891a229 749
10bc17b6 750#endif /* USE_REENTRANT_API */
751
752#endif
753
754EOF
755
756close(H);
757
aa418cf1 758# Prepare to write the reentr.c.
759
10bc17b6 760die "reentr.c: $!" unless open(C, ">reentr.c");
761select C;
762print <<EOF;
763/*
764 * reentr.c
765 *
4bb101f2 766 * Copyright (C) 2002, 2003, by Larry Wall and others
10bc17b6 767 *
768 * You may distribute under the terms of either the GNU General Public
769 * License or the Artistic License, as specified in the README file.
770 *
771 * !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
61296642 772 * This file is built by reentr.pl from data in reentr.pl.
10bc17b6 773 *
774 * "Saruman," I said, standing away from him, "only one hand at a time can
775 * wield the One, and you know that well, so do not trouble to say we!"
776 *
61296642 777 * This file contains a collection of automatically created wrappers
778 * (created by running reentr.pl) for reentrant (thread-safe) versions of
779 * various library calls, such as getpwent_r. The wrapping is done so
780 * that other files like pp_sys.c calling those library functions need not
781 * care about the differences between various platforms' idiosyncrasies
782 * regarding these reentrant interfaces.
10bc17b6 783 */
784
785#include "EXTERN.h"
786#define PERL_IN_REENTR_C
787#include "perl.h"
788#include "reentr.h"
789
790void
791Perl_reentrant_size(pTHX) {
792#ifdef USE_REENTRANT_API
8695fa85 793#define REENTRANTSMALLSIZE 256 /* Make something up. */
794#define REENTRANTUSUALSIZE 4096 /* Make something up. */
10bc17b6 795@size
796#endif /* USE_REENTRANT_API */
797}
798
799void
800Perl_reentrant_init(pTHX) {
801#ifdef USE_REENTRANT_API
802 New(31337, PL_reentrant_buffer, 1, REENTR);
803 Perl_reentrant_size(aTHX);
804@init
805#endif /* USE_REENTRANT_API */
806}
807
808void
809Perl_reentrant_free(pTHX) {
810#ifdef USE_REENTRANT_API
811@free
812 Safefree(PL_reentrant_buffer);
813#endif /* USE_REENTRANT_API */
814}
815
edd309b7 816void*
817Perl_reentrant_retry(const char *f, ...)
818{
27da23d5 819 dVAR; dTHX;
edd309b7 820 void *retptr = NULL;
821#ifdef USE_REENTRANT_API
0891a229 822# if defined(USE_HOSTENT_BUFFER) || defined(USE_GRENT_BUFFER) || defined(USE_NETENT_BUFFER) || defined(USE_PWENT_BUFFER) || defined(USE_PROTOENT_BUFFER) || defined(USE_SERVENT_BUFFER)
e3410746 823 void *p0;
824# endif
f7937171 825# if defined(USE_SERVENT_BUFFER)
e3410746 826 void *p1;
827# endif
f7937171 828# if defined(USE_HOSTENT_BUFFER)
edd309b7 829 size_t asize;
e3410746 830# endif
f7937171 831# if defined(USE_HOSTENT_BUFFER) || defined(USE_NETENT_BUFFER) || defined(USE_PROTOENT_BUFFER) || defined(USE_SERVENT_BUFFER)
edd309b7 832 int anint;
e3410746 833# endif
edd309b7 834 va_list ap;
835
836 va_start(ap, f);
837
edd309b7 838 switch (PL_op->op_type) {
f7937171 839#ifdef USE_HOSTENT_BUFFER
edd309b7 840 case OP_GHBYADDR:
841 case OP_GHBYNAME:
842 case OP_GHOSTENT:
843 {
af685957 844#ifdef PERL_REENTRANT_MAXSIZE
845 if (PL_reentrant_buffer->_hostent_size <=
846 PERL_REENTRANT_MAXSIZE / 2)
847#endif
848 {
f7937171 849 PL_reentrant_buffer->_hostent_size *= 2;
850 Renew(PL_reentrant_buffer->_hostent_buffer,
851 PL_reentrant_buffer->_hostent_size, char);
edd309b7 852 switch (PL_op->op_type) {
853 case OP_GHBYADDR:
854 p0 = va_arg(ap, void *);
855 asize = va_arg(ap, size_t);
856 anint = va_arg(ap, int);
857 retptr = gethostbyaddr(p0, asize, anint); break;
858 case OP_GHBYNAME:
859 p0 = va_arg(ap, void *);
f6f0b69b 860 retptr = gethostbyname((char *)p0); break;
edd309b7 861 case OP_GHOSTENT:
862 retptr = gethostent(); break;
863 default:
0de8cad8 864 SETERRNO(ERANGE, LIB_INVARG);
edd309b7 865 break;
866 }
867 }
868 }
869 break;
870#endif
f7937171 871#ifdef USE_GRENT_BUFFER
edd309b7 872 case OP_GGRNAM:
873 case OP_GGRGID:
874 case OP_GGRENT:
875 {
af685957 876#ifdef PERL_REENTRANT_MAXSIZE
877 if (PL_reentrant_buffer->_grent_size <=
878 PERL_REENTRANT_MAXSIZE / 2)
879#endif
880 {
edd309b7 881 Gid_t gid;
f7937171 882 PL_reentrant_buffer->_grent_size *= 2;
883 Renew(PL_reentrant_buffer->_grent_buffer,
884 PL_reentrant_buffer->_grent_size, char);
edd309b7 885 switch (PL_op->op_type) {
886 case OP_GGRNAM:
887 p0 = va_arg(ap, void *);
f6f0b69b 888 retptr = getgrnam((char *)p0); break;
edd309b7 889 case OP_GGRGID:
ab2b559b 890#if Gid_t_size < INTSIZE
891 gid = (Gid_t)va_arg(ap, int);
892#else
edd309b7 893 gid = va_arg(ap, Gid_t);
ab2b559b 894#endif
edd309b7 895 retptr = getgrgid(gid); break;
896 case OP_GGRENT:
897 retptr = getgrent(); break;
898 default:
0de8cad8 899 SETERRNO(ERANGE, LIB_INVARG);
edd309b7 900 break;
901 }
902 }
903 }
904 break;
905#endif
f7937171 906#ifdef USE_NETENT_BUFFER
edd309b7 907 case OP_GNBYADDR:
908 case OP_GNBYNAME:
909 case OP_GNETENT:
910 {
af685957 911#ifdef PERL_REENTRANT_MAXSIZE
912 if (PL_reentrant_buffer->_netent_size <=
913 PERL_REENTRANT_MAXSIZE / 2)
914#endif
915 {
edd309b7 916 Netdb_net_t net;
f7937171 917 PL_reentrant_buffer->_netent_size *= 2;
918 Renew(PL_reentrant_buffer->_netent_buffer,
919 PL_reentrant_buffer->_netent_size, char);
edd309b7 920 switch (PL_op->op_type) {
921 case OP_GNBYADDR:
922 net = va_arg(ap, Netdb_net_t);
923 anint = va_arg(ap, int);
924 retptr = getnetbyaddr(net, anint); break;
925 case OP_GNBYNAME:
926 p0 = va_arg(ap, void *);
f6f0b69b 927 retptr = getnetbyname((char *)p0); break;
edd309b7 928 case OP_GNETENT:
929 retptr = getnetent(); break;
930 default:
0de8cad8 931 SETERRNO(ERANGE, LIB_INVARG);
edd309b7 932 break;
933 }
934 }
935 }
936 break;
937#endif
f7937171 938#ifdef USE_PWENT_BUFFER
edd309b7 939 case OP_GPWNAM:
940 case OP_GPWUID:
941 case OP_GPWENT:
942 {
af685957 943#ifdef PERL_REENTRANT_MAXSIZE
944 if (PL_reentrant_buffer->_pwent_size <=
945 PERL_REENTRANT_MAXSIZE / 2)
946#endif
947 {
edd309b7 948 Uid_t uid;
f7937171 949 PL_reentrant_buffer->_pwent_size *= 2;
950 Renew(PL_reentrant_buffer->_pwent_buffer,
951 PL_reentrant_buffer->_pwent_size, char);
edd309b7 952 switch (PL_op->op_type) {
953 case OP_GPWNAM:
954 p0 = va_arg(ap, void *);
f6f0b69b 955 retptr = getpwnam((char *)p0); break;
edd309b7 956 case OP_GPWUID:
ab2b559b 957#if Uid_t_size < INTSIZE
958 uid = (Uid_t)va_arg(ap, int);
959#else
edd309b7 960 uid = va_arg(ap, Uid_t);
ab2b559b 961#endif
edd309b7 962 retptr = getpwuid(uid); break;
963 case OP_GPWENT:
964 retptr = getpwent(); break;
965 default:
0de8cad8 966 SETERRNO(ERANGE, LIB_INVARG);
edd309b7 967 break;
968 }
969 }
970 }
971 break;
972#endif
f7937171 973#ifdef USE_PROTOENT_BUFFER
edd309b7 974 case OP_GPBYNAME:
975 case OP_GPBYNUMBER:
976 case OP_GPROTOENT:
977 {
af685957 978#ifdef PERL_REENTRANT_MAXSIZE
979 if (PL_reentrant_buffer->_protoent_size <=
980 PERL_REENTRANT_MAXSIZE / 2)
981#endif
982 {
f7937171 983 PL_reentrant_buffer->_protoent_size *= 2;
984 Renew(PL_reentrant_buffer->_protoent_buffer,
985 PL_reentrant_buffer->_protoent_size, char);
edd309b7 986 switch (PL_op->op_type) {
987 case OP_GPBYNAME:
988 p0 = va_arg(ap, void *);
f6f0b69b 989 retptr = getprotobyname((char *)p0); break;
edd309b7 990 case OP_GPBYNUMBER:
991 anint = va_arg(ap, int);
992 retptr = getprotobynumber(anint); break;
993 case OP_GPROTOENT:
994 retptr = getprotoent(); break;
995 default:
0de8cad8 996 SETERRNO(ERANGE, LIB_INVARG);
edd309b7 997 break;
998 }
999 }
1000 }
1001 break;
1002#endif
f7937171 1003#ifdef USE_SERVENT_BUFFER
edd309b7 1004 case OP_GSBYNAME:
1005 case OP_GSBYPORT:
1006 case OP_GSERVENT:
1007 {
af685957 1008#ifdef PERL_REENTRANT_MAXSIZE
1009 if (PL_reentrant_buffer->_servent_size <=
1010 PERL_REENTRANT_MAXSIZE / 2)
1011#endif
1012 {
f7937171 1013 PL_reentrant_buffer->_servent_size *= 2;
1014 Renew(PL_reentrant_buffer->_servent_buffer,
1015 PL_reentrant_buffer->_servent_size, char);
edd309b7 1016 switch (PL_op->op_type) {
1017 case OP_GSBYNAME:
1018 p0 = va_arg(ap, void *);
1019 p1 = va_arg(ap, void *);
f6f0b69b 1020 retptr = getservbyname((char *)p0, (char *)p1); break;
edd309b7 1021 case OP_GSBYPORT:
1022 anint = va_arg(ap, int);
1023 p0 = va_arg(ap, void *);
f6f0b69b 1024 retptr = getservbyport(anint, (char *)p0); break;
edd309b7 1025 case OP_GSERVENT:
1026 retptr = getservent(); break;
1027 default:
0de8cad8 1028 SETERRNO(ERANGE, LIB_INVARG);
edd309b7 1029 break;
1030 }
1031 }
1032 }
1033 break;
1034#endif
1035 default:
1036 /* Not known how to retry, so just fail. */
1037 break;
1038 }
1039
1040 va_end(ap);
1041#endif
1042 return retptr;
1043}
1044
10bc17b6 1045EOF
1046
1047__DATA__
1048asctime S |time |const struct tm|B_SB|B_SBI|I_SB|I_SBI
b430fd04 1049crypt CC |crypt |struct crypt_data|B_CCS|B_CCD|D=CRYPTD*
10bc17b6 1050ctermid B |stdio | |B_B
1051ctime S |time |const time_t |B_SB|B_SBI|I_SB|I_SBI
1052drand48 |stdlib |struct drand48_data |I_ST|T=double*
1053endgrent |grp | |I_H|V_H
31ee0cb7 1054endhostent |netdb | |I_D|V_D|D=struct hostent_data*
1055endnetent |netdb | |I_D|V_D|D=struct netent_data*
1056endprotoent |netdb | |I_D|V_D|D=struct protoent_data*
10bc17b6 1057endpwent |pwd | |I_H|V_H
31ee0cb7 1058endservent |netdb | |I_D|V_D|D=struct servent_data*
10bc17b6 1059getgrent |grp |struct group |I_SBWR|I_SBIR|S_SBW|S_SBI|I_SBI|I_SBIH
1060getgrgid T |grp |struct group |I_TSBWR|I_TSBIR|I_TSBI|S_TSBI|T=gid_t
1061getgrnam C |grp |struct group |I_CSBWR|I_CSBIR|S_CBI|I_CSBI|S_CSBI
a845a0d4 1062gethostbyaddr CWI |netdb |struct hostent |I_CWISBWRE|S_CWISBWIE|S_CWISBIE|S_TWISBIE|S_CIISBIE|S_CSBIE|S_TSBIE|I_CWISD|I_CIISD|I_CII|I_TsISBWRE|D=struct hostent_data*|T=const void*|s=socklen_t
10bc17b6 1063gethostbyname C |netdb |struct hostent |I_CSBWRE|S_CSBIE|I_CSD|D=struct hostent_data*
1064gethostent |netdb |struct hostent |I_SBWRE|I_SBIE|S_SBIE|S_SBI|I_SBI|I_SD|D=struct hostent_data*
f6f0b69b 1065getlogin |unistd |char |I_BW|I_BI|B_BW|B_BI
a845a0d4 1066getnetbyaddr LI |netdb |struct netent |I_UISBWRE|I_LISBI|S_TISBI|S_LISBI|I_TISD|I_LISD|I_IISD|I_uISBWRE|D=struct netent_data*|T=in_addr_t|U=unsigned long|u=uint32_t
10bc17b6 1067getnetbyname C |netdb |struct netent |I_CSBWRE|I_CSBI|S_CSBI|I_CSD|D=struct netent_data*
1068getnetent |netdb |struct netent |I_SBWRE|I_SBIE|S_SBIE|S_SBI|I_SBI|I_SD|D=struct netent_data*
1069getprotobyname C|netdb |struct protoent|I_CSBWR|S_CSBI|I_CSD|D=struct protoent_data*
1070getprotobynumber I |netdb |struct protoent|I_ISBWR|S_ISBI|I_ISD|D=struct protoent_data*
1071getprotoent |netdb |struct protoent|I_SBWR|I_SBI|S_SBI|I_SD|D=struct protoent_data*
1072getpwent |pwd |struct passwd |I_SBWR|I_SBIR|S_SBW|S_SBI|I_SBI|I_SBIH
1073getpwnam C |pwd |struct passwd |I_CSBWR|I_CSBIR|S_CSBI|I_CSBI
1074getpwuid T |pwd |struct passwd |I_TSBWR|I_TSBIR|I_TSBI|S_TSBI|T=uid_t
1075getservbyname CC|netdb |struct servent |I_CCSBWR|S_CCSBI|I_CCSD|D=struct servent_data*
1076getservbyport IC|netdb |struct servent |I_ICSBWR|S_ICSBI|I_ICSD|D=struct servent_data*
1077getservent |netdb |struct servent |I_SBWR|I_SBI|S_SBI|I_SD|D=struct servent_data*
1078getspnam C |shadow |struct spwd |I_CSBWR|S_CSBI
1079gmtime T |time |struct tm |S_TS|I_TS|T=const time_t*
1080localtime T |time |struct tm |S_TS|I_TS|T=const time_t*
a845a0d4 1081random |stdlib |struct random_data|I_iS|I_lS|I_St|i=int*|l=long*|t=int32_t*
10bc17b6 1082readdir T |dirent |struct dirent |I_TSR|I_TS|T=DIR*
1083readdir64 T |dirent |struct dirent64|I_TSR|I_TS|T=DIR*
1084setgrent |grp | |I_H|V_H
1085sethostent I |netdb | |I_ID|V_ID|D=struct hostent_data*
1086setlocale IC |locale | |I_ICBI
1087setnetent I |netdb | |I_ID|V_ID|D=struct netent_data*
1088setprotoent I |netdb | |I_ID|V_ID|D=struct protoent_data*
1089setpwent |pwd | |I_H|V_H
1090setservent I |netdb | |I_ID|V_ID|D=struct servent_data*
1091srand48 L |stdlib |struct drand48_data |I_LS
1092srandom T |stdlib |struct random_data|I_TS|T=unsigned int
1093strerror I |string | |I_IBW|I_IBI|B_IBW
1094tmpnam B |stdio | |B_B
1095ttyname I |unistd | |I_IBW|I_IBI|B_IBI