This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
We now have symbols for llrint and llround.
[perl5.git] / ext / POSIX / POSIX.xs
CommitLineData
6e22d046
JH
1#define PERL_EXT_POSIX
2
2986a63f
JH
3#ifdef NETWARE
4 #define _POSIX_
4efcf9a2
SB
5 /*
6 * Ideally this should be somewhere down in the includes
7 * but putting it in other places is giving compiler errors.
8 * Also here I am unable to check for HAS_UNAME since it wouldn't have
9 * yet come into the file at this stage - sgp 18th Oct 2000
10 */
2986a63f
JH
11 #include <sys/utsname.h>
12#endif /* NETWARE */
13
c5be433b
GS
14#define PERL_NO_GET_CONTEXT
15
463ee0b2 16#include "EXTERN.h"
760ac839 17#define PERLIO_NOT_STDIO 1
463ee0b2
LW
18#include "perl.h"
19#include "XSUB.h"
acfe0abc 20#if defined(PERL_IMPLICIT_SYS)
873ef191
GS
21# undef signal
22# undef open
cd661bb6 23# undef setmode
35ff7856 24# define open PerlLIO_open3
873ef191 25#endif
2304df62 26#include <ctype.h>
a0d0e21e 27#ifdef I_DIRENT /* XXX maybe better to just rely on perl.h? */
2304df62 28#include <dirent.h>
a0d0e21e 29#endif
2304df62 30#include <errno.h>
b0ba2190
SH
31#ifdef WIN32
32#include <sys/errno2.h>
33#endif
2304df62
AD
34#ifdef I_FLOAT
35#include <float.h>
36#endif
a5713e21
JH
37#ifdef I_FENV
38#include <fenv.h>
39#endif
a0d0e21e 40#ifdef I_LIMITS
2304df62 41#include <limits.h>
a0d0e21e 42#endif
2304df62
AD
43#include <locale.h>
44#include <math.h>
85e6fe83 45#ifdef I_PWD
2304df62 46#include <pwd.h>
85e6fe83 47#endif
2304df62
AD
48#include <setjmp.h>
49#include <signal.h>
2304df62 50#include <stdarg.h>
17c3b450 51
2304df62
AD
52#ifdef I_STDDEF
53#include <stddef.h>
54#endif
6990d991 55
b5846a0b
BS
56#ifdef I_UNISTD
57#include <unistd.h>
58#endif
59
05b4a618
JH
60#if defined(USE_QUADMATH) && defined(I_QUADMATH)
61
62# undef M_E
63# undef M_LOG2E
64# undef M_LOG10E
65# undef M_LN2
66# undef M_LN10
67# undef M_PI
68# undef M_PI_2
69# undef M_PI_4
70# undef M_1_PI
71# undef M_2_PI
72# undef M_2_SQRTPI
73# undef M_SQRT2
74# undef M_SQRT1_2
75
76# define M_E M_Eq
77# define M_LOG2E M_LOG2Eq
78# define M_LOG10E M_LOG10Eq
79# define M_LN2 M_LN2q
80# define M_LN10 M_LN10q
81# define M_PI M_PIq
82# define M_PI_2 M_PI_2q
83# define M_PI_4 M_PI_4q
84# define M_1_PI M_1_PIq
85# define M_2_PI M_2_PIq
86# define M_2_SQRTPI M_2_SQRTPIq
87# define M_SQRT2 M_SQRT2q
88# define M_SQRT1_2 M_SQRT1_2q
89
90#else
91
92# ifndef M_E
93# define M_E 2.71828182845904523536028747135266250
94# endif
95# ifndef M_LOG2E
96# define M_LOG2E 1.44269504088896340735992468100189214
97# endif
98# ifndef M_LOG10E
99# define M_LOG10E 0.434294481903251827651128918916605082
100# endif
101# ifndef M_LN2
102# define M_LN2 0.693147180559945309417232121458176568
103# endif
104# ifndef M_LN10
105# define M_LN10 2.30258509299404568401799145468436421
106# endif
107# ifndef M_PI
108# define M_PI 3.14159265358979323846264338327950288
109# endif
110# ifndef M_PI_2
111# define M_PI_2 1.57079632679489661923132169163975144
112# endif
113# ifndef M_PI_4
114# define M_PI_4 0.785398163397448309615660845819875721
115# endif
116# ifndef M_1_PI
117# define M_1_PI 0.318309886183790671537767526745028724
118# endif
119# ifndef M_2_PI
120# define M_2_PI 0.636619772367581343075535053490057448
121# endif
122# ifndef M_2_SQRTPI
123# define M_2_SQRTPI 1.12837916709551257389615890312154517
124# endif
125# ifndef M_SQRT2
126# define M_SQRT2 1.41421356237309504880168872420969808
127# endif
128# ifndef M_SQRT1_2
129# define M_SQRT1_2 0.707106781186547524400844362104849039
130# endif
131
39b5f1c4
JH
132#endif
133
a5f1a7e5
JH
134#if !defined(INFINITY) && defined(NV_INF)
135# define INFINITY NV_INF
136#endif
137
138#if !defined(NAN) && defined(NV_NAN)
139# define NAN NV_NAN
140#endif
141
142#if !defined(Inf) && defined(NV_INF)
143# define Inf NV_INF
144#endif
145
146#if !defined(NaN) && defined(NV_NAN)
147# define NaN NV_NAN
148#endif
149
935e3c48 150/* We will have an emulation. */
3f8e6f93 151#ifndef FP_INFINITE
935e3c48
JH
152# define FP_INFINITE 0
153# define FP_NAN 1
154# define FP_NORMAL 2
155# define FP_SUBNORMAL 3
156# define FP_ZERO 4
157#endif
158
e0939537
JH
159/* We will have an emulation. */
160#ifndef FE_TONEAREST
ebac59ac
JH
161# define FE_TOWARDZERO 0
162# define FE_TONEAREST 1
163# define FE_UPWARD 2
164# define FE_DOWNWARD 3
e0939537
JH
165#endif
166
7965edec
JH
167/* C89 math.h:
168
169 acos asin atan atan2 ceil cos cosh exp fabs floor fmod frexp ldexp
170 log log10 modf pow sin sinh sqrt tan tanh
171
172 * Implemented in core:
173
174 atan2 cos exp log pow sin sqrt
175
9d233e12 176 * C99 math.h added:
7965edec 177
9d233e12
JH
178 acosh asinh atanh cbrt copysign erf erfc exp2 expm1 fdim fma fmax
179 fmin fpclassify hypot ilogb isfinite isgreater isgreaterequal isinf
180 isless islessequal islessgreater isnan isnormal isunordered lgamma
9e010b89 181 log1p log2 logb lrint lround nan nearbyint nextafter nexttoward remainder
9d233e12 182 remquo rint round scalbn signbit tgamma trunc
7965edec 183
36467c3a
JH
184 See:
185 http://pubs.opengroup.org/onlinepubs/009695399/basedefs/math.h.html
186
26e0f0d3 187 * Berkeley/SVID extensions:
7965edec 188
26e0f0d3 189 j0 j1 jn y0 y1 yn
7965edec 190
427d28ce 191 * Configure already (5.21.5) scans for:
d2bce0fd 192
427d28ce 193 copysign*l* fpclassify isfinite isinf isnan isnan*l* ilogb*l* signbit scalbn*l*
d2bce0fd 194
26e0f0d3 195 * For floating-point round mode (which matters for e.g. lrint and rint)
9d233e12 196
26e0f0d3 197 fegetround fesetround
9d233e12 198
7965edec
JH
199*/
200
9d233e12
JH
201/* XXX Constant FP_FAST_FMA (if true, FMA is faster) */
202
5716d070
JH
203/* XXX Add ldiv(), lldiv()? It's C99, but from stdlib.h, not math.h */
204
39b5f1c4 205/* XXX Beware old gamma() -- one cannot know whether that is the
d334ccbe
JH
206 * gamma or the log of gamma, that's why the new tgamma and lgamma.
207 * Though also remember tgamma_r and lgamma_r. */
39b5f1c4
JH
208
209/* XXX The truthiness of acosh() is the canary for all of the
d2bce0fd 210 * C99 math. This is very likely wrong, especially in non-UNIX lands
d334ccbe
JH
211 * like Win32 and VMS, but also older UNIXes have issues. For Win32,
212 * and other non-fully-C99, we later do some undefines for these interfaces.
d2bce0fd
JH
213 *
214 * But we are very trying very hard to avoid introducing separate Configure
215 * symbols for all the 40-ish new math symbols. Especially since the set
216 * of missing functions doesn't seem to follow any patterns. */
bfce4ab3 217
5716d070 218#ifdef HAS_ACOSH
e0972548
JH
219
220/* Certain AIX releases have the C99 math, but not in long double.
221 * The <math.h> has them, e.g. __expl128, but no library has them!
78c93c95 222 *
42f1389c 223 * Also see the comments in hints/aix.sh about long doubles. */
e0972548 224
05b4a618
JH
225# if defined(USE_QUADMATH) && defined(I_QUADMATH)
226# define c99_acosh acoshq
227# define c99_asinh asinhq
228# define c99_atanh atanhq
229# define c99_cbrt cbrtq
230# define c99_copysign copysignq
231# define c99_erf erfq
232# define c99_erfc erfcq
233/* no exp2q */
234# define c99_expm1 expm1q
235# define c99_fdim fdimq
236# define c99_fma fmaq
237# define c99_fmax fmaxq
238# define c99_fmin fminq
239# define c99_hypot hypotq
240# define c99_ilogb ilogbq
241# define c99_lgamma lgammaq
242# define c99_log1p log1pq
243# define c99_log2 log2q
244/* no logbq */
245/* no llrintq */
246/* no llroundq */
247# define c99_lrint lrintq
248# define c99_lround lroundq
249# define c99_nan nanq
250# define c99_nearbyint nearbyintq
251# define c99_nextafter nextafterq
252/* no nexttowardq */
253# define c99_remainder remainderq
254# define c99_remquo remquoq
255# define c99_rint rintq
256# define c99_round roundq
257# define c99_scalbn scalbnq
258# define c99_signbit signbitq
42db6422 259# define c99_tgamma tgammaq
05b4a618
JH
260# define c99_trunc truncq
261# define bessel_j0 j0q
262# define bessel_j1 j1q
263# define bessel_jn jnq
264# define bessel_y0 y0q
265# define bessel_y1 y1q
266# define bessel_yn ynq
267# elif defined(USE_LONG_DOUBLE) && \
22192125
JH
268 (defined(HAS_FREXPL) || defined(HAS_ILOGBL)) && defined(HAS_SQRTL)
269/* Use some of the Configure scans for long double math functions
270 * as the canary for all the C99 *l variants being defined. */
7965edec
JH
271# define c99_acosh acoshl
272# define c99_asinh asinhl
273# define c99_atanh atanhl
274# define c99_cbrt cbrtl
275# define c99_copysign copysignl
7965edec
JH
276# define c99_erf erfl
277# define c99_erfc erfcl
278# define c99_exp2 exp2l
279# define c99_expm1 expm1l
280# define c99_fdim fdiml
281# define c99_fma fmal
282# define c99_fmax fmaxl
283# define c99_fmin fminl
284# define c99_hypot hypotl
285# define c99_ilogb ilogbl
002ae7aa 286# define c99_lgamma lgammal
7965edec
JH
287# define c99_log1p log1pl
288# define c99_log2 log2l
289# define c99_logb logbl
290# if defined(USE_64_BIT_INT) && QUADKIND == QUAD_IS_LONG_LONG
291# define c99_lrint llrintl
292# else
293# define c99_lrint lrintl
294# endif
9e010b89
JH
295# if defined(USE_64_BIT_INT) && QUADKIND == QUAD_IS_LONG_LONG
296# define c99_lround llroundl
297# else
298# define c99_lround lroundl
299# endif
7965edec
JH
300# define c99_nan nanl
301# define c99_nearbyint nearbyintl
302# define c99_nextafter nextafterl
303# define c99_nexttoward nexttowardl
304# define c99_remainder remainderl
305# define c99_remquo remquol
306# define c99_rint rintl
307# define c99_round roundl
308# define c99_scalbn scalbnl
5716d070
JH
309# ifdef HAS_SIGNBIT /* possibly bad assumption */
310# define c99_signbit signbitl
311# endif
7965edec
JH
312# define c99_tgamma tgammal
313# define c99_trunc truncl
314# else
315# define c99_acosh acosh
316# define c99_asinh asinh
317# define c99_atanh atanh
318# define c99_cbrt cbrt
319# define c99_copysign copysign
7965edec
JH
320# define c99_erf erf
321# define c99_erfc erfc
322# define c99_exp2 exp2
323# define c99_expm1 expm1
324# define c99_fdim fdim
325# define c99_fma fma
326# define c99_fmax fmax
327# define c99_fmin fmin
328# define c99_hypot hypot
329# define c99_ilogb ilogb
330# define c99_lgamma lgamma
331# define c99_log1p log1p
332# define c99_log2 log2
333# define c99_logb logb
29f617b7 334# if defined(USE_64_BIT_INT) && QUADKIND == QUAD_IS_LONG_LONG && defined(HAS_LLRINT)
7965edec
JH
335# define c99_lrint llrint
336# else
337# define c99_lrint lrint
338# endif
29f617b7 339# if defined(USE_64_BIT_INT) && QUADKIND == QUAD_IS_LONG_LONG && defined(HAS_LLROUND)
9e010b89
JH
340# define c99_lround llround
341# else
342# define c99_lround lround
343# endif
7965edec
JH
344# define c99_nan nan
345# define c99_nearbyint nearbyint
346# define c99_nextafter nextafter
347# define c99_nexttoward nexttoward
348# define c99_remainder remainder
349# define c99_remquo remquo
350# define c99_rint rint
351# define c99_round round
352# define c99_scalbn scalbn
5716d070
JH
353/* We already define Perl_signbit in perl.h. */
354# ifdef HAS_SIGNBIT
355# define c99_signbit signbit
356# endif
7965edec
JH
357# define c99_tgamma tgamma
358# define c99_trunc trunc
359# endif
03397f96 360
92d982a3
JH
361# ifndef isunordered
362# ifdef Perl_isnan
363# define isunordered(x, y) (Perl_isnan(x) || Perl_isnan(y))
364# elif defined(HAS_UNORDERED)
365# define isunordered(x, y) unordered(x, y)
366# endif
2bf3fd6f
JH
367# endif
368
a0d9739d
JH
369/* XXX these isgreater/isnormal/isunordered macros definitions should
370 * be moved further in the file to be part of the emulations, so that
371 * platforms can e.g. #undef c99_isunordered and have it work like
372 * it does for the other interfaces. */
373
2bf3fd6f
JH
374# if !defined(isgreater) && defined(isunordered)
375# define isgreater(x, y) (!isunordered((x), (y)) && (x) > (y))
376# define isgreaterequal(x, y) (!isunordered((x), (y)) && (x) >= (y))
377# define isless(x, y) (!isunordered((x), (y)) && (x) < (y))
378# define islessequal(x, y) (!isunordered((x), (y)) && (x) <= (y))
379# define islessgreater(x, y) (!isunordered((x), (y)) && \
380 ((x) > (y) || (y) > (x)))
381# endif
382
03397f96
JH
383/* Check both the Configure symbol and the macro-ness (like C99 promises). */
384# if defined(HAS_FPCLASSIFY) && defined(fpclassify)
385# define c99_fpclassify fpclassify
03397f96
JH
386# endif
387/* Like isnormal(), the isfinite(), isinf(), and isnan() are also C99
388 and also (sizeof-arg-aware) macros, but they are already well taken
389 care of by Configure et al, and defined in perl.h as
390 Perl_isfinite(), Perl_isinf(), and Perl_isnan(). */
391# ifdef isnormal
5716d070 392# define c99_isnormal isnormal
03397f96 393# endif
5716d070 394# ifdef isgreater /* canary for all the C99 is*<cmp>* macros. */
03397f96
JH
395# define c99_isgreater isgreater
396# define c99_isgreaterequal isgreaterequal
397# define c99_isless isless
398# define c99_islessequal islessequal
399# define c99_islessgreater islessgreater
400# define c99_isunordered isunordered
401# endif
7965edec
JH
402#endif
403
360baf49
JH
404/* If on legacy platforms, and not using gcc, some C99 math interfaces
405 * might be missing, turn them off so that the emulations hopefully
406 * kick in. This is admittedly nasty, and fragile, but the alternative
53e66ff6
JH
407 * is to have Configure scans for all the 40+ interfaces.
408 *
409 * In other words: if you have an incomplete (or broken) C99 math interface,
410 * #undef the c99_foo here, and let the emulations kick in. */
411
817e8fe1 412#ifndef __GNUC__
360baf49 413
360baf49
JH
414# if defined(__osf__) /* Tru64 */
415# undef c99_fdim
416# undef c99_fma
417# undef c99_fmax
418# undef c99_fmin
419# undef c99_fpclassify
420# undef c99_isfinite
421# undef c99_isinf
6b4ee168 422/* Tru64 is missing isunordered but we have emulation. */
360baf49 423# undef c99_lrint
9e010b89 424# undef c99_lround
7c7d45f1 425# undef c99_nan /* in libm, but seems broken (no proto, either) */
360baf49
JH
426# undef c99_nearbyint
427# undef c99_nexttoward
428# undef c99_remquo
360baf49
JH
429# undef c99_round
430# undef c99_scalbn
431# endif
432
d2bce0fd
JH
433#endif
434
c0cd65b2
CB
435/* XXX Regarding C99 math.h, VMS seems to be missing these:
436
9e010b89 437 lround nan nearbyint round scalbn llrint
c0cd65b2
CB
438 */
439
440#ifdef __VMS
9e010b89 441# undef c99_lround
c0cd65b2
CB
442# undef c99_nan
443# undef c99_nearbyint
444# undef c99_round
445# undef c99_scalbn
51a0624d
CB
446/* Have lrint but not llrint. */
447# if defined(USE_64_BIT_INT) && QUADKIND == QUAD_IS_LONG_LONG
448# undef c99_lrint
449# endif
c0cd65b2
CB
450#endif
451
bfce4ab3
JH
452/* XXX Regarding C99 math.h, Win32 seems to be missing these:
453
3b422749 454 erf erfc exp2 fdim fma fmax fmin fpclassify ilogb lgamma log1p log2 lrint
bfce4ab3
JH
455 remquo rint signbit tgamma trunc
456
457 Win32 does seem to have these:
458
3b422749 459 acosh asinh atanh cbrt copysign cosh expm1 hypot log10 nan
bfce4ab3
JH
460 nearbyint nextafter nexttoward remainder round scalbn
461
462 And the Bessel functions are defined like _this.
463*/
39b5f1c4 464
bfce4ab3 465#ifdef WIN32
3b422749
JH
466# undef c99_erf
467# undef c99_erfc
bfce4ab3
JH
468# undef c99_exp2
469# undef c99_fdim
470# undef c99_fma
471# undef c99_fmax
472# undef c99_fmin
473# undef c99_ilogb
474# undef c99_lgamma
475# undef c99_log1p
476# undef c99_log2
477# undef c99_lrint
9e010b89 478# undef c99_lround
bfce4ab3
JH
479# undef c99_remquo
480# undef c99_rint
481# undef c99_signbit
482# undef c99_tgamma
483# undef c99_trunc
39b5f1c4
JH
484
485/* Some APIs exist under Win32 with "underbar" names. */
486# undef c99_hypot
487# undef c99_logb
488# undef c99_nextafter
489# define c99_hypot _hypot
490# define c99_logb _logb
491# define c99_nextafter _nextafter
492
85c93440
JH
493# define bessel_j0 _j0
494# define bessel_j1 _j1
495# define bessel_jn _jn
496# define bessel_y0 _y0
497# define bessel_y1 _y1
498# define bessel_yn _yn
499
5716d070 500#endif
bfce4ab3 501
1dfc8cb8
JH
502#ifdef __CYGWIN__
503# undef c99_nexttoward
504#endif
505
39b5f1c4 506/* The Bessel functions: BSD, SVID, XPG4, and POSIX. But not C99. */
05b4a618 507#if defined(HAS_J0) && !defined(bessel_j0)
5716d070
JH
508# if defined(USE_LONG_DOUBLE) && defined(HAS_J0L)
509# define bessel_j0 j0l
510# define bessel_j1 j1l
511# define bessel_jn jnl
512# define bessel_y0 y0l
513# define bessel_y1 y1l
514# define bessel_yn ynl
515# else
85c93440
JH
516# define bessel_j0 j0
517# define bessel_j1 j1
518# define bessel_jn jn
519# define bessel_y0 y0
520# define bessel_y1 y1
521# define bessel_yn yn
5716d070 522# endif
bfce4ab3
JH
523#endif
524
39b5f1c4 525/* Emulations for missing math APIs.
bfce4ab3
JH
526 *
527 * Keep in mind that the point of many of these functions is that
528 * they, if available, are supposed to give more precise/more
39b5f1c4
JH
529 * numerically stable results.
530 *
531 * See e.g. http://www.johndcook.com/math_h.html
532 */
533
39b5f1c4
JH
534#ifndef c99_acosh
535static NV my_acosh(NV x)
536{
537 return Perl_log(x + Perl_sqrt(x * x - 1));
538}
539# define c99_acosh my_acosh
540#endif
541
542#ifndef c99_asinh
543static NV my_asinh(NV x)
544{
545 return Perl_log(x + Perl_sqrt(x * x + 1));
546}
547# define c99_asinh my_asinh
548#endif
549
550#ifndef c99_atanh
551static NV my_atanh(NV x)
552{
553 return (Perl_log(1 + x) - Perl_log(1 - x)) / 2;
554}
555# define c99_atanh my_atanh
556#endif
557
558#ifndef c99_cbrt
559static NV my_cbrt(NV x)
560{
561 static const NV one_third = (NV)1.0/3;
562 return x >= 0.0 ? Perl_pow(x, one_third) : -Perl_pow(-x, one_third);
563}
564# define c99_cbrt my_cbrt
565#endif
566
567#ifndef c99_copysign
568static NV my_copysign(NV x, NV y)
569{
570 return y >= 0 ? (x < 0 ? -x : x) : (x < 0 ? x : -x);
571}
572# define c99_copysign my_copysign
573#endif
574
1ae51000 575/* XXX cosh (though c89) */
d5f4f26a 576
7895eac5
JH
577#ifndef c99_erf
578static NV my_erf(NV x)
579{
580 /* http://www.johndcook.com/cpp_erf.html -- public domain */
581 NV a1 = 0.254829592;
582 NV a2 = -0.284496736;
583 NV a3 = 1.421413741;
584 NV a4 = -1.453152027;
585 NV a5 = 1.061405429;
586 NV p = 0.3275911;
efc74307 587 NV t, y;
7895eac5
JH
588 int sign = x < 0 ? -1 : 1; /* Save the sign. */
589 x = PERL_ABS(x);
590
591 /* Abramowitz and Stegun formula 7.1.26 */
efc74307 592 t = 1.0 / (1.0 + p * x);
6347c79c 593 y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1) * t * Perl_exp(-x*x);
7895eac5
JH
594
595 return sign * y;
596}
597# define c99_erf my_erf
598#endif
599
ffbadafb
JH
600#ifndef c99_erfc
601static NV my_erfc(NV x) {
aed13ba6
JH
602 /* This is not necessarily numerically stable, but better than nothing. */
603 return 1.0 - c99_erf(x);
ffbadafb
JH
604}
605# define c99_erfc my_erfc
606#endif
d5f4f26a 607
39b5f1c4
JH
608#ifndef c99_exp2
609static NV my_exp2(NV x)
610{
611 return Perl_pow((NV)2.0, x);
612}
613# define c99_exp2 my_exp2
614#endif
615
616#ifndef c99_expm1
617static NV my_expm1(NV x)
618{
619 if (PERL_ABS(x) < 1e-5)
7895eac5 620 /* http://www.johndcook.com/cpp_expm1.html -- public domain.
2783359f 621 * Taylor series, the first four terms (the last term quartic). */
39b5f1c4 622 /* Probably not enough for long doubles. */
2783359f 623 return x * (1.0 + x * (1/2.0 + x * (1/6.0 + x/24.0)));
39b5f1c4
JH
624 else
625 return Perl_exp(x) - 1;
626}
627# define c99_expm1 my_expm1
628#endif
629
630#ifndef c99_fdim
631static NV my_fdim(NV x, NV y)
632{
633 return x > y ? x - y : 0;
634}
635# define c99_fdim my_fdim
636#endif
637
638#ifndef c99_fmax
639static NV my_fmax(NV x, NV y)
640{
641 if (Perl_isnan(x)) {
642 return Perl_isnan(y) ? NV_NAN : y;
643 } else if (Perl_isnan(y)) {
644 return x;
645 }
646 return x > y ? x : y;
647}
648# define c99_fmax my_fmax
649#endif
650
651#ifndef c99_fmin
652static NV my_fmin(NV x, NV y)
653{
654 if (Perl_isnan(x)) {
655 return Perl_isnan(y) ? NV_NAN : y;
656 } else if (Perl_isnan(y)) {
657 return x;
658 }
659 return x < y ? x : y;
660}
661# define c99_fmin my_fmin
662#endif
663
26e0f0d3
JH
664#ifndef c99_fpclassify
665
ea464252 666static IV my_fpclassify(NV x)
935e3c48 667{
c3607571 668#ifdef Perl_fp_class_inf
935e3c48
JH
669 if (Perl_fp_class_inf(x)) return FP_INFINITE;
670 if (Perl_fp_class_nan(x)) return FP_NAN;
671 if (Perl_fp_class_norm(x)) return FP_NORMAL;
672 if (Perl_fp_class_denorm(x)) return FP_SUBNORMAL;
673 if (Perl_fp_class_zero(x)) return FP_ZERO;
935e3c48
JH
674# define c99_fpclassify my_fpclassify
675#endif
c3607571 676 return -1;
935e3c48 677}
935e3c48 678
26e0f0d3
JH
679#endif
680
39b5f1c4
JH
681#ifndef c99_hypot
682static NV my_hypot(NV x, NV y)
683{
7bbf2c9b
JH
684 /* http://en.wikipedia.org/wiki/Hypot */
685 NV t;
686 x = PERL_ABS(x); /* Take absolute values. */
687 if (y == 0)
688 return x;
689 if (Perl_isnan(y))
690 return NV_INF;
691 y = PERL_ABS(y);
692 if (x < y) { /* Swap so that y is less. */
693 t = x;
694 x = y;
695 y = t;
39b5f1c4 696 }
7bbf2c9b 697 t = y / x;
6347c79c 698 return x * Perl_sqrt(1.0 + t * t);
39b5f1c4
JH
699}
700# define c99_hypot my_hypot
701#endif
702
703#ifndef c99_ilogb
704static IV my_ilogb(NV x)
705{
706 return (IV)(Perl_log(x) * M_LOG2E);
707}
708# define c99_ilogb my_ilogb
709#endif
710
d5f4f26a
JH
711/* XXX lgamma -- non-trivial */
712
39b5f1c4
JH
713#ifndef c99_log1p
714static NV my_log1p(NV x)
715{
7895eac5 716 /* http://www.johndcook.com/cpp_log_one_plus_x.html -- public domain.
2783359f 717 * Taylor series, the first four terms (the last term quartic). */
3ae4cd6c 718 if (x < -1.0)
731a2bdb 719 return NV_NAN;
3ae4cd6c
JH
720 if (x == -1.0)
721 return -NV_INF;
39b5f1c4
JH
722 if (PERL_ABS(x) > 1e-4)
723 return Perl_log(1.0 + x);
724 else
725 /* Probably not enough for long doubles. */
2783359f 726 return x * (1.0 + x * (-1/2.0 + x * (1/3.0 - x/4.0)));
39b5f1c4
JH
727}
728# define c99_log1p my_log1p
729#endif
730
731#ifndef c99_log2
732static NV my_log2(NV x)
733{
734 return Perl_log(x) * M_LOG2E;
735}
736# define c99_log2 my_log2
737#endif
738
d5f4f26a
JH
739/* XXX nextafter */
740
741/* XXX nexttoward */
742
743static int my_fegetround()
744{
745#ifdef HAS_FEGETROUND
746 return fegetround();
e0939537
JH
747#elif defined(HAS_FPGETROUND)
748 switch (fpgetround()) {
e0939537
JH
749 case FP_RN: return FE_TONEAREST;
750 case FP_RZ: return FE_TOWARDZERO;
751 case FP_RM: return FE_DOWNWARD;
cc639810 752 case FP_RP: return FE_UPWARD;
9d491117 753 default: return -1;
e0939537 754 }
c35bb41d
JH
755#elif defined(FLT_ROUNDS)
756 switch (FLT_ROUNDS) {
c35bb41d 757 case 0: return FE_TOWARDZERO;
ebac59ac
JH
758 case 1: return FE_TONEAREST;
759 case 2: return FE_UPWARD;
760 case 3: return FE_DOWNWARD;
c35bb41d
JH
761 default: return -1;
762 }
877206df
JH
763#elif defined(__osf__) /* Tru64 */
764 switch (read_rnd()) {
765 case FP_RND_RN: return FE_TONEAREST;
766 case FP_RND_RZ: return FE_TOWARDZERO;
767 case FP_RND_RM: return FE_DOWNWARD;
768 case FP_RND_RP: return FE_UPWARD;
769 default: return -1;
770 }
d5f4f26a
JH
771#else
772 return -1;
773#endif
774}
775
c4125715
JH
776/* Toward closest integer. */
777#define MY_ROUND_NEAREST(x) ((NV)((IV)((x) >= 0.0 ? (x) + 0.5 : (x) - 0.5)))
778
779/* Toward zero. */
780#define MY_ROUND_TRUNC(x) ((NV)((IV)(x)))
781
e0939537 782/* Toward minus infinity. */
c4125715 783#define MY_ROUND_DOWN(x) ((NV)((IV)((x) >= 0.0 ? (x) : (x) - 0.5)))
e0939537
JH
784
785/* Toward plus infinity. */
c4125715 786#define MY_ROUND_UP(x) ((NV)((IV)((x) >= 0.0 ? (x) + 0.5 : (x))))
e0939537 787
5a4dabf8 788#if (!defined(c99_nearbyint) || !defined(c99_lrint)) && defined(FE_TONEAREST)
d5f4f26a
JH
789static NV my_rint(NV x)
790{
791#ifdef FE_TONEAREST
792 switch (my_fegetround()) {
c4125715
JH
793 case FE_TONEAREST: return MY_ROUND_NEAREST(x);
794 case FE_TOWARDZERO: return MY_ROUND_TRUNC(x);
795 case FE_DOWNWARD: return MY_ROUND_DOWN(x);
796 case FE_UPWARD: return MY_ROUND_UP(x);
9d491117 797 default: return NV_NAN;
e0939537
JH
798 }
799#elif defined(HAS_FPGETROUND)
800 switch (fpgetround()) {
c4125715
JH
801 case FP_RN: return MY_ROUND_NEAREST(x);
802 case FP_RZ: return MY_ROUND_TRUNC(x);
803 case FP_RM: return MY_ROUND_DOWN(x);
804 case FE_RP: return MY_ROUND_UP(x);
9d491117 805 default: return NV_NAN;
d5f4f26a
JH
806 }
807#else
808 return NV_NAN;
809#endif
810}
5a4dabf8 811#endif
d5f4f26a
JH
812
813/* XXX nearbyint() and rint() are not really identical -- but the difference
814 * is messy: nearbyint is defined NOT to raise FE_INEXACT floating point
815 * exceptions, while rint() is defined to MAYBE raise them. At the moment
816 * Perl is blissfully unaware of such fine detail of floating point. */
817#ifndef c99_nearbyint
818# ifdef FE_TONEAREST
819# define c99_nearbyrint my_rint
820# endif
821#endif
822
823#ifndef c99_lrint
824# ifdef FE_TONEAREST
c40e90c4 825static IV my_lrint(NV x)
d5f4f26a
JH
826{
827 return (IV)my_rint(x);
828}
829# define c99_lrint my_lrint
830# endif
831#endif
832
9e010b89
JH
833#ifndef c99_lround
834static IV my_lround(NV x)
835{
c63c00af 836 return (IV)MY_ROUND_NEAREST(x);
9e010b89
JH
837}
838# define c99_lround my_lround
839#endif
840
d5f4f26a
JH
841/* XXX remainder */
842
843/* XXX remquo */
844
845#ifndef c99_rint
846# ifdef FE_TONEAREST
847# define c99_rint my_rint
848# endif
849#endif
850
39b5f1c4
JH
851#ifndef c99_round
852static NV my_round(NV x)
853{
c4125715 854 return MY_ROUND_NEAREST(x);
39b5f1c4
JH
855}
856# define c99_round my_round
857#endif
858
859#ifndef c99_scalbn
93ddb856 860# if defined(Perl_ldexp) && FLT_RADIX == 2
ea464252 861static NV my_scalbn(NV x, int y)
39b5f1c4
JH
862{
863 return Perl_ldexp(x, y);
864}
865# define c99_scalbn my_scalbn
866# endif
867#endif
868
1ae51000 869/* XXX sinh (though c89) */
39b5f1c4
JH
870
871#ifndef c99_tgamma
872# ifdef c99_lgamma
873static NV my_tgamma(NV x)
874{
875 double l = c99_lgamma(x);
876 return signgam * Perl_exp(l); /* XXX evil global signgam, need lgamma_r */
877}
d5f4f26a
JH
878# define c99_tgamma my_tgamma
879/* XXX tgamma without lgamma -- non-trivial */
39b5f1c4
JH
880# endif
881#endif
bfce4ab3 882
1ae51000 883/* XXX tanh (though c89) */
d5f4f26a
JH
884
885#ifndef c99_trunc
886static NV my_trunc(NV x)
887{
c4125715 888 return MY_ROUND_TRUNC(x);
d5f4f26a
JH
889}
890# define c99_trunc my_trunc
891#endif
892
3609ea0d 893/* XXX This comment is just to make I_TERMIO and I_SGTTY visible to
a0d0e21e
LW
894 metaconfig for future extension writers. We don't use them in POSIX.
895 (This is really sneaky :-) --AD
896*/
897#if defined(I_TERMIOS)
898#include <termios.h>
899#endif
a0d0e21e 900#ifdef I_STDLIB
2304df62 901#include <stdlib.h>
a0d0e21e 902#endif
5518ecd4 903#ifndef __ultrix__
2304df62 904#include <string.h>
5518ecd4 905#endif
2304df62 906#include <sys/stat.h>
2304df62 907#include <sys/types.h>
2304df62 908#include <time.h>
6dead956 909#ifdef I_UNISTD
1d2dff63 910#include <unistd.h>
6dead956 911#endif
71be2cbc 912#include <fcntl.h>
913
e2465f50 914#ifdef HAS_TZNAME
fb207d52 915# if !defined(WIN32) && !defined(__CYGWIN__) && !defined(NETWARE) && !defined(__UWIN__)
e2465f50
JH
916extern char *tzname[];
917# endif
918#else
fb207d52 919#if !defined(WIN32) && !defined(__UWIN__) || (defined(__MINGW32__) && !defined(tzname))
e2465f50
JH
920char *tzname[] = { "" , "" };
921#endif
cb2479a8
JH
922#endif
923
6c418a22 924#if defined(__VMS) && !defined(__POSIX_SOURCE)
294c8bc4
CB
925
926# include <utsname.h>
6c418a22 927
6990d991 928# undef mkfifo
6c418a22 929# define mkfifo(a,b) (not_here("mkfifo"),-1)
6c418a22 930
931 /* The POSIX notion of ttyname() is better served by getname() under VMS */
932 static char ttnambuf[64];
933# define ttyname(fd) (isatty(fd) > 0 ? getname(fd,ttnambuf,0) : NULL)
934
6c418a22 935#else
d308986b 936#if defined (__CYGWIN__)
f89d6eaa
EF
937# define tzname _tzname
938#endif
2986a63f 939#if defined (WIN32) || defined (NETWARE)
6990d991 940# undef mkfifo
6dead956 941# define mkfifo(a,b) not_here("mkfifo")
873ef191 942# define ttyname(a) (char*)not_here("ttyname")
6dead956 943# define sigset_t long
86200d5c 944# define pid_t long
6dead956
GS
945# ifdef _MSC_VER
946# define mode_t short
947# endif
62520c91
GS
948# ifdef __MINGW32__
949# define mode_t short
f6c6487a
GS
950# ifndef tzset
951# define tzset() not_here("tzset")
952# endif
953# ifndef _POSIX_OPEN_MAX
954# define _POSIX_OPEN_MAX FOPEN_MAX /* XXX bogus ? */
955# endif
62520c91 956# endif
6dead956
GS
957# define sigaction(a,b,c) not_here("sigaction")
958# define sigpending(a) not_here("sigpending")
959# define sigprocmask(a,b,c) not_here("sigprocmask")
960# define sigsuspend(a) not_here("sigsuspend")
961# define sigemptyset(a) not_here("sigemptyset")
962# define sigaddset(a,b) not_here("sigaddset")
963# define sigdelset(a,b) not_here("sigdelset")
964# define sigfillset(a) not_here("sigfillset")
965# define sigismember(a,b) not_here("sigismember")
2986a63f 966#ifndef NETWARE
6e22d046
JH
967# undef setuid
968# undef setgid
2986a63f
JH
969# define setuid(a) not_here("setuid")
970# define setgid(a) not_here("setgid")
971#endif /* NETWARE */
73e21afd 972# define strtold(s1,s2) not_here("strtold")
6dead956 973#else
6990d991
JH
974
975# ifndef HAS_MKFIFO
e37778c2 976# if defined(OS2)
d6a255e6 977# define mkfifo(a,b) not_here("mkfifo")
3609ea0d 978# else /* !( defined OS2 ) */
d6a255e6
IZ
979# ifndef mkfifo
980# define mkfifo(path, mode) (mknod((path), (mode) | S_IFIFO, 0))
981# endif
6990d991
JH
982# endif
983# endif /* !HAS_MKFIFO */
984
e37778c2
NC
985# ifdef I_GRP
986# include <grp.h>
987# endif
988# include <sys/times.h>
989# ifdef HAS_UNAME
990# include <sys/utsname.h>
6c418a22 991# endif
e37778c2 992# include <sys/wait.h>
6c418a22 993# ifdef I_UTIME
994# include <utime.h>
995# endif
2986a63f 996#endif /* WIN32 || NETWARE */
6dead956 997#endif /* __VMS */
2304df62
AD
998
999typedef int SysRet;
a0d0e21e 1000typedef long SysRetLong;
2304df62
AD
1001typedef sigset_t* POSIX__SigSet;
1002typedef HV* POSIX__SigAction;
a0d0e21e
LW
1003#ifdef I_TERMIOS
1004typedef struct termios* POSIX__Termios;
1005#else /* Define termios types to int, and call not_here for the functions.*/
1006#define POSIX__Termios int
1007#define speed_t int
1008#define tcflag_t int
1009#define cc_t int
1010#define cfgetispeed(x) not_here("cfgetispeed")
1011#define cfgetospeed(x) not_here("cfgetospeed")
1012#define tcdrain(x) not_here("tcdrain")
1013#define tcflush(x,y) not_here("tcflush")
1014#define tcsendbreak(x,y) not_here("tcsendbreak")
1015#define cfsetispeed(x,y) not_here("cfsetispeed")
1016#define cfsetospeed(x,y) not_here("cfsetospeed")
1017#define ctermid(x) (char *) not_here("ctermid")
1018#define tcflow(x,y) not_here("tcflow")
1019#define tcgetattr(x,y) not_here("tcgetattr")
1020#define tcsetattr(x,y,z) not_here("tcsetattr")
1021#endif
1022
1023/* Possibly needed prototypes */
6e22d046 1024#ifndef WIN32
a2e65780 1025START_EXTERN_C
20ce7b12
GS
1026double strtod (const char *, char **);
1027long strtol (const char *, char **, int);
1028unsigned long strtoul (const char *, char **, int);
0ff7b9da
JH
1029#ifdef HAS_STRTOLD
1030long double strtold (const char *, char **);
1031#endif
a2e65780 1032END_EXTERN_C
6e22d046 1033#endif
a0d0e21e 1034
a0d0e21e
LW
1035#ifndef HAS_DIFFTIME
1036#ifndef difftime
1037#define difftime(a,b) not_here("difftime")
1038#endif
1039#endif
1040#ifndef HAS_FPATHCONF
3609ea0d 1041#define fpathconf(f,n) (SysRetLong) not_here("fpathconf")
a0d0e21e
LW
1042#endif
1043#ifndef HAS_MKTIME
1044#define mktime(a) not_here("mktime")
8990e307
LW
1045#endif
1046#ifndef HAS_NICE
1047#define nice(a) not_here("nice")
1048#endif
a0d0e21e 1049#ifndef HAS_PATHCONF
3609ea0d 1050#define pathconf(f,n) (SysRetLong) not_here("pathconf")
a0d0e21e
LW
1051#endif
1052#ifndef HAS_SYSCONF
3609ea0d 1053#define sysconf(n) (SysRetLong) not_here("sysconf")
a0d0e21e 1054#endif
8990e307
LW
1055#ifndef HAS_READLINK
1056#define readlink(a,b,c) not_here("readlink")
1057#endif
1058#ifndef HAS_SETPGID
1059#define setpgid(a,b) not_here("setpgid")
1060#endif
8990e307
LW
1061#ifndef HAS_SETSID
1062#define setsid() not_here("setsid")
1063#endif
a0d0e21e
LW
1064#ifndef HAS_STRCOLL
1065#define strcoll(s1,s2) not_here("strcoll")
1066#endif
a89d8a78
DH
1067#ifndef HAS_STRTOD
1068#define strtod(s1,s2) not_here("strtod")
1069#endif
0ff7b9da
JH
1070#ifndef HAS_STRTOLD
1071#define strtold(s1,s2) not_here("strtold")
1072#endif
a89d8a78
DH
1073#ifndef HAS_STRTOL
1074#define strtol(s1,s2,b) not_here("strtol")
1075#endif
1076#ifndef HAS_STRTOUL
1077#define strtoul(s1,s2,b) not_here("strtoul")
1078#endif
a0d0e21e
LW
1079#ifndef HAS_STRXFRM
1080#define strxfrm(s1,s2,n) not_here("strxfrm")
8990e307
LW
1081#endif
1082#ifndef HAS_TCGETPGRP
1083#define tcgetpgrp(a) not_here("tcgetpgrp")
1084#endif
1085#ifndef HAS_TCSETPGRP
1086#define tcsetpgrp(a,b) not_here("tcsetpgrp")
1087#endif
1088#ifndef HAS_TIMES
2986a63f 1089#ifndef NETWARE
8990e307 1090#define times(a) not_here("times")
2986a63f 1091#endif /* NETWARE */
8990e307
LW
1092#endif
1093#ifndef HAS_UNAME
1094#define uname(a) not_here("uname")
1095#endif
1096#ifndef HAS_WAITPID
1097#define waitpid(a,b,c) not_here("waitpid")
1098#endif
1099
a0d0e21e
LW
1100#ifndef HAS_MBLEN
1101#ifndef mblen
1102#define mblen(a,b) not_here("mblen")
1103#endif
1104#endif
1105#ifndef HAS_MBSTOWCS
1106#define mbstowcs(s, pwcs, n) not_here("mbstowcs")
1107#endif
1108#ifndef HAS_MBTOWC
1109#define mbtowc(pwc, s, n) not_here("mbtowc")
1110#endif
1111#ifndef HAS_WCSTOMBS
1112#define wcstombs(s, pwcs, n) not_here("wcstombs")
1113#endif
1114#ifndef HAS_WCTOMB
1115#define wctomb(s, wchar) not_here("wcstombs")
1116#endif
1117#if !defined(HAS_MBLEN) && !defined(HAS_MBSTOWCS) && !defined(HAS_MBTOWC) && !defined(HAS_WCSTOMBS) && !defined(HAS_WCTOMB)
1118/* If we don't have these functions, then we wouldn't have gotten a typedef
1119 for wchar_t, the wide character type. Defining wchar_t allows the
1120 functions referencing it to compile. Its actual type is then meaningless,
1121 since without the above functions, all sections using it end up calling
1122 not_here() and croak. --Kaveh Ghazi (ghazi@noc.rutgers.edu) 9/18/94. */
1123#ifndef wchar_t
1124#define wchar_t char
1125#endif
1126#endif
1127
3f3bcbfc
KW
1128#ifndef HAS_LOCALECONV
1129# define localeconv() not_here("localeconv")
1130#else
2f0945cb
NC
1131struct lconv_offset {
1132 const char *name;
1133 size_t offset;
1134};
1135
1136const struct lconv_offset lconv_strings[] = {
03ceeedf 1137#ifdef USE_LOCALE_NUMERIC
3800c318
JH
1138 {"decimal_point", STRUCT_OFFSET(struct lconv, decimal_point)},
1139 {"thousands_sep", STRUCT_OFFSET(struct lconv, thousands_sep)},
03ceeedf 1140# ifndef NO_LOCALECONV_GROUPING
3800c318 1141 {"grouping", STRUCT_OFFSET(struct lconv, grouping)},
03ceeedf 1142# endif
2f0945cb 1143#endif
03ceeedf 1144#ifdef USE_LOCALE_MONETARY
3800c318
JH
1145 {"int_curr_symbol", STRUCT_OFFSET(struct lconv, int_curr_symbol)},
1146 {"currency_symbol", STRUCT_OFFSET(struct lconv, currency_symbol)},
1147 {"mon_decimal_point", STRUCT_OFFSET(struct lconv, mon_decimal_point)},
03ceeedf 1148# ifndef NO_LOCALECONV_MON_THOUSANDS_SEP
3800c318 1149 {"mon_thousands_sep", STRUCT_OFFSET(struct lconv, mon_thousands_sep)},
03ceeedf
KW
1150# endif
1151# ifndef NO_LOCALECONV_MON_GROUPING
3800c318 1152 {"mon_grouping", STRUCT_OFFSET(struct lconv, mon_grouping)},
03ceeedf 1153# endif
3800c318
JH
1154 {"positive_sign", STRUCT_OFFSET(struct lconv, positive_sign)},
1155 {"negative_sign", STRUCT_OFFSET(struct lconv, negative_sign)},
03ceeedf 1156#endif
2f0945cb
NC
1157 {NULL, 0}
1158};
1159
c1284011
KW
1160#ifdef USE_LOCALE_NUMERIC
1161
1162/* The Linux man pages say these are the field names for the structure
1163 * components that are LC_NUMERIC; the rest being LC_MONETARY */
1164# define isLC_NUMERIC_STRING(name) (strcmp(name, "decimal_point") \
1165 || strcmp(name, "thousands_sep") \
1166 \
1167 /* There should be no harm done \
1168 * checking for this, even if \
1169 * NO_LOCALECONV_GROUPING */ \
1170 || strcmp(name, "grouping"))
1171#else
1172# define isLC_NUMERIC_STRING(name) (0)
1173#endif
1174
2f0945cb 1175const struct lconv_offset lconv_integers[] = {
03ceeedf 1176#ifdef USE_LOCALE_MONETARY
3800c318
JH
1177 {"int_frac_digits", STRUCT_OFFSET(struct lconv, int_frac_digits)},
1178 {"frac_digits", STRUCT_OFFSET(struct lconv, frac_digits)},
1179 {"p_cs_precedes", STRUCT_OFFSET(struct lconv, p_cs_precedes)},
1180 {"p_sep_by_space", STRUCT_OFFSET(struct lconv, p_sep_by_space)},
1181 {"n_cs_precedes", STRUCT_OFFSET(struct lconv, n_cs_precedes)},
1182 {"n_sep_by_space", STRUCT_OFFSET(struct lconv, n_sep_by_space)},
1183 {"p_sign_posn", STRUCT_OFFSET(struct lconv, p_sign_posn)},
1184 {"n_sign_posn", STRUCT_OFFSET(struct lconv, n_sign_posn)},
b15c1b56
AF
1185#ifdef HAS_LC_MONETARY_2008
1186 {"int_p_cs_precedes", STRUCT_OFFSET(struct lconv, int_p_cs_precedes)},
1187 {"int_p_sep_by_space", STRUCT_OFFSET(struct lconv, int_p_sep_by_space)},
1188 {"int_n_cs_precedes", STRUCT_OFFSET(struct lconv, int_n_cs_precedes)},
1189 {"int_n_sep_by_space", STRUCT_OFFSET(struct lconv, int_n_sep_by_space)},
1190 {"int_p_sign_posn", STRUCT_OFFSET(struct lconv, int_p_sign_posn)},
1191 {"int_n_sign_posn", STRUCT_OFFSET(struct lconv, int_n_sign_posn)},
1192#endif
03ceeedf 1193#endif
2f0945cb
NC
1194 {NULL, 0}
1195};
1196
3f3bcbfc 1197#endif /* HAS_LOCALECONV */
a0d0e21e 1198
172ea7c8 1199#ifdef HAS_LONG_DOUBLE
53796371 1200# if LONG_DOUBLESIZE > NVSIZE
172ea7c8
JH
1201# undef HAS_LONG_DOUBLE /* XXX until we figure out how to use them */
1202# endif
1203#endif
1204
1205#ifndef HAS_LONG_DOUBLE
1206#ifdef LDBL_MAX
1207#undef LDBL_MAX
1208#endif
1209#ifdef LDBL_MIN
1210#undef LDBL_MIN
1211#endif
1212#ifdef LDBL_EPSILON
1213#undef LDBL_EPSILON
1214#endif
1215#endif
1216
ec193bec
JH
1217/* Background: in most systems the low byte of the wait status
1218 * is the signal (the lowest 7 bits) and the coredump flag is
1219 * the eight bit, and the second lowest byte is the exit status.
1220 * BeOS bucks the trend and has the bytes in different order.
1221 * See beos/beos.c for how the reality is bent even in BeOS
1222 * to follow the traditional. However, to make the POSIX
1223 * wait W*() macros to work in BeOS, we need to unbend the
1224 * reality back in place. --jhi */
17028706
IW
1225/* In actual fact the code below is to blame here. Perl has an internal
1226 * representation of the exit status ($?), which it re-composes from the
1227 * OS's representation using the W*() POSIX macros. The code below
1228 * incorrectly uses the W*() macros on the internal representation,
1229 * which fails for OSs that have a different representation (namely BeOS
1230 * and Haiku). WMUNGE() is a hack that converts the internal
1231 * representation into the OS specific one, so that the W*() macros work
1232 * as expected. The better solution would be not to use the W*() macros
1233 * in the first place, though. -- Ingo Weinhold
1234 */
b6c36746 1235#if defined(__HAIKU__)
ec193bec
JH
1236# define WMUNGE(x) (((x) & 0xFF00) >> 8 | ((x) & 0x00FF) << 8)
1237#else
1238# define WMUNGE(x) (x)
1239#endif
1240
8990e307 1241static int
4b48cf39 1242not_here(const char *s)
8990e307
LW
1243{
1244 croak("POSIX::%s not implemented on this architecture", s);
1245 return -1;
1246}
463ee0b2 1247
1cb0fb50 1248#include "const-c.inc"
a290f238 1249
1dfe7606 1250static void
40b7a5f5 1251restore_sigmask(pTHX_ SV *osset_sv)
1dfe7606 1252{
7feb700b
JH
1253 /* Fortunately, restoring the signal mask can't fail, because
1254 * there's nothing we can do about it if it does -- we're not
1255 * supposed to return -1 from sigaction unless the disposition
1256 * was unaffected.
1257 */
7feb700b
JH
1258 sigset_t *ossetp = (sigset_t *) SvPV_nolen( osset_sv );
1259 (void)sigprocmask(SIG_SETMASK, ossetp, (sigset_t *)0);
1dfe7606
AJ
1260}
1261
a2261f90
NC
1262static void *
1263allocate_struct(pTHX_ SV *rv, const STRLEN size, const char *packname) {
1264 SV *const t = newSVrv(rv, packname);
1265 void *const p = sv_grow(t, size + 1);
1266
1267 SvCUR_set(t, size);
1268 SvPOK_on(t);
1269 return p;
1270}
1271
81ab4c44
SH
1272#ifdef WIN32
1273
1274/*
1275 * (1) The CRT maintains its own copy of the environment, separate from
1276 * the Win32API copy.
1277 *
1278 * (2) CRT getenv() retrieves from this copy. CRT putenv() updates this
1279 * copy, and then calls SetEnvironmentVariableA() to update the Win32API
1280 * copy.
1281 *
1282 * (3) win32_getenv() and win32_putenv() call GetEnvironmentVariableA() and
1283 * SetEnvironmentVariableA() directly, bypassing the CRT copy of the
1284 * environment.
1285 *
1286 * (4) The CRT strftime() "%Z" implementation calls __tzset(). That
1287 * calls CRT tzset(), but only the first time it is called, and in turn
1288 * that uses CRT getenv("TZ") to retrieve the timezone info from the CRT
1289 * local copy of the environment and hence gets the original setting as
1290 * perl never updates the CRT copy when assigning to $ENV{TZ}.
1291 *
1292 * Therefore, we need to retrieve the value of $ENV{TZ} and call CRT
1293 * putenv() to update the CRT copy of the environment (if it is different)
1294 * whenever we're about to call tzset().
1295 *
1296 * In addition to all that, when perl is built with PERL_IMPLICIT_SYS
1297 * defined:
1298 *
1299 * (a) Each interpreter has its own copy of the environment inside the
1300 * perlhost structure. That allows applications that host multiple
1301 * independent Perl interpreters to isolate environment changes from
1302 * each other. (This is similar to how the perlhost mechanism keeps a
1303 * separate working directory for each Perl interpreter, so that calling
1304 * chdir() will not affect other interpreters.)
1305 *
1306 * (b) Only the first Perl interpreter instantiated within a process will
1307 * "write through" environment changes to the process environment.
1308 *
1309 * (c) Even the primary Perl interpreter won't update the CRT copy of the
1310 * the environment, only the Win32API copy (it calls win32_putenv()).
1311 *
1312 * As with CPerlHost::Getenv() and CPerlHost::Putenv() themselves, it makes
1313 * sense to only update the process environment when inside the main
1314 * interpreter, but we don't have access to CPerlHost's m_bTopLevel member
1315 * from here so we'll just have to check PL_curinterp instead.
1316 *
1317 * Therefore, we can simply #undef getenv() and putenv() so that those names
1318 * always refer to the CRT functions, and explicitly call win32_getenv() to
1319 * access perl's %ENV.
1320 *
1321 * We also #undef malloc() and free() to be sure we are using the CRT
1322 * functions otherwise under PERL_IMPLICIT_SYS they are redefined to calls
1323 * into VMem::Malloc() and VMem::Free() and all allocations will be freed
1324 * when the Perl interpreter is being destroyed so we'd end up with a pointer
1325 * into deallocated memory in environ[] if a program embedding a Perl
1326 * interpreter continues to operate even after the main Perl interpreter has
1327 * been destroyed.
1328 *
1329 * Note that we don't free() the malloc()ed memory unless and until we call
1330 * malloc() again ourselves because the CRT putenv() function simply puts its
b7b1e41b 1331 * pointer argument into the environ[] array (it doesn't make a copy of it)
81ab4c44
SH
1332 * so this memory must otherwise be leaked.
1333 */
1334
1335#undef getenv
1336#undef putenv
1337#undef malloc
1338#undef free
1339
1340static void
1341fix_win32_tzenv(void)
1342{
1343 static char* oldenv = NULL;
1344 char* newenv;
1345 const char* perl_tz_env = win32_getenv("TZ");
1346 const char* crt_tz_env = getenv("TZ");
1347 if (perl_tz_env == NULL)
1348 perl_tz_env = "";
1349 if (crt_tz_env == NULL)
1350 crt_tz_env = "";
1351 if (strcmp(perl_tz_env, crt_tz_env) != 0) {
1352 newenv = (char*)malloc((strlen(perl_tz_env) + 4) * sizeof(char));
1353 if (newenv != NULL) {
1354 sprintf(newenv, "TZ=%s", perl_tz_env);
1355 putenv(newenv);
1356 if (oldenv != NULL)
1357 free(oldenv);
1358 oldenv = newenv;
1359 }
1360 }
1361}
1362
1363#endif
1364
1365/*
1366 * my_tzset - wrapper to tzset() with a fix to make it work (better) on Win32.
1367 * This code is duplicated in the Time-Piece module, so any changes made here
1368 * should be made there too.
1369 */
1370static void
1371my_tzset(pTHX)
1372{
1373#ifdef WIN32
1374#if defined(USE_ITHREADS) && defined(PERL_IMPLICIT_SYS)
1375 if (PL_curinterp == aTHX)
1376#endif
1377 fix_win32_tzenv();
1378#endif
1379 tzset();
1380}
1381
fb52dbc1
NC
1382typedef int (*isfunc_t)(int);
1383typedef void (*any_dptr_t)(void *);
1384
1385/* This needs to be ALIASed in a custom way, hence can't easily be defined as
1386 a regular XSUB. */
1387static XSPROTO(is_common); /* prototype to pass -Wmissing-prototypes */
1388static XSPROTO(is_common)
1389{
1390 dXSARGS;
2da736a2 1391
fb52dbc1
NC
1392 if (items != 1)
1393 croak_xs_usage(cv, "charstring");
1394
1395 {
1396 dXSTARG;
1397 STRLEN len;
31e107a4
KW
1398 /*int RETVAL = 0; YYY means uncomment this to return false on an
1399 * empty string input */
fb52dbc1
NC
1400 int RETVAL;
1401 unsigned char *s = (unsigned char *) SvPV(ST(0), len);
1402 unsigned char *e = s + len;
1403 isfunc_t isfunc = (isfunc_t) XSANY.any_dptr;
1404
2da736a2
KW
1405 if (ckWARN_d(WARN_DEPRECATED)) {
1406
1407 /* Warn exactly once for each lexical place this function is
1408 * called. See thread at
1409 * http://markmail.org/thread/jhqcag5njmx7jpyu */
1410
5c45bbe0
TC
1411 HV *warned = get_hv("POSIX::_warned", GV_ADD | GV_ADDMULTI);
1412 if (! hv_exists(warned, (const char *)&PL_op, sizeof(PL_op))) {
2da736a2
KW
1413 Perl_warner(aTHX_ packWARN(WARN_DEPRECATED),
1414 "Calling POSIX::%"HEKf"() is deprecated",
1415 HEKfARG(GvNAME_HEK(CvGV(cv))));
5c45bbe0 1416 hv_store(warned, (const char *)&PL_op, sizeof(PL_op), &PL_sv_yes, 0);
2da736a2
KW
1417 }
1418 }
1419
31e107a4 1420 /*if (e > s) { YYY */
fb52dbc1
NC
1421 for (RETVAL = 1; RETVAL && s < e; s++)
1422 if (!isfunc(*s))
1423 RETVAL = 0;
31e107a4 1424 /*} YYY */
fb52dbc1
NC
1425 XSprePUSH;
1426 PUSHi((IV)RETVAL);
1427 }
1428 XSRETURN(1);
1429}
1430
1431MODULE = POSIX PACKAGE = POSIX
1432
1433BOOT:
1434{
1435 CV *cv;
1436 const char *file = __FILE__;
1437
df164f52
DM
1438
1439 /* silence compiler warning about not_here() defined but not used */
1440 if (0) not_here("");
1441
fb52dbc1
NC
1442 /* Ensure we get the function, not a macro implementation. Like the C89
1443 standard says we can... */
1444#undef isalnum
1445 cv = newXS("POSIX::isalnum", is_common, file);
1446 XSANY.any_dptr = (any_dptr_t) &isalnum;
1447#undef isalpha
1448 cv = newXS("POSIX::isalpha", is_common, file);
1449 XSANY.any_dptr = (any_dptr_t) &isalpha;
1450#undef iscntrl
1451 cv = newXS("POSIX::iscntrl", is_common, file);
1452 XSANY.any_dptr = (any_dptr_t) &iscntrl;
1453#undef isdigit
1454 cv = newXS("POSIX::isdigit", is_common, file);
1455 XSANY.any_dptr = (any_dptr_t) &isdigit;
1456#undef isgraph
1457 cv = newXS("POSIX::isgraph", is_common, file);
1458 XSANY.any_dptr = (any_dptr_t) &isgraph;
1459#undef islower
1460 cv = newXS("POSIX::islower", is_common, file);
1461 XSANY.any_dptr = (any_dptr_t) &islower;
1462#undef isprint
1463 cv = newXS("POSIX::isprint", is_common, file);
1464 XSANY.any_dptr = (any_dptr_t) &isprint;
1465#undef ispunct
1466 cv = newXS("POSIX::ispunct", is_common, file);
1467 XSANY.any_dptr = (any_dptr_t) &ispunct;
1468#undef isspace
1469 cv = newXS("POSIX::isspace", is_common, file);
1470 XSANY.any_dptr = (any_dptr_t) &isspace;
1471#undef isupper
1472 cv = newXS("POSIX::isupper", is_common, file);
1473 XSANY.any_dptr = (any_dptr_t) &isupper;
1474#undef isxdigit
1475 cv = newXS("POSIX::isxdigit", is_common, file);
1476 XSANY.any_dptr = (any_dptr_t) &isxdigit;
1477}
1478
2304df62
AD
1479MODULE = SigSet PACKAGE = POSIX::SigSet PREFIX = sig
1480
92b39396 1481void
2304df62 1482new(packname = "POSIX::SigSet", ...)
d3f5e399 1483 const char * packname
2304df62
AD
1484 CODE:
1485 {
1486 int i;
92b39396
NC
1487 sigset_t *const s
1488 = (sigset_t *) allocate_struct(aTHX_ (ST(0) = sv_newmortal()),
1489 sizeof(sigset_t),
1490 packname);
1491 sigemptyset(s);
a0d0e21e 1492 for (i = 1; i < items; i++)
92b39396
NC
1493 sigaddset(s, SvIV(ST(i)));
1494 XSRETURN(1);
2304df62 1495 }
2304df62
AD
1496
1497SysRet
df6c2df2 1498addset(sigset, sig)
2304df62
AD
1499 POSIX::SigSet sigset
1500 int sig
df6c2df2
NC
1501 ALIAS:
1502 delset = 1
1503 CODE:
1504 RETVAL = ix ? sigdelset(sigset, sig) : sigaddset(sigset, sig);
1505 OUTPUT:
1506 RETVAL
2304df62
AD
1507
1508SysRet
df6c2df2 1509emptyset(sigset)
2304df62 1510 POSIX::SigSet sigset
df6c2df2
NC
1511 ALIAS:
1512 fillset = 1
1513 CODE:
1514 RETVAL = ix ? sigfillset(sigset) : sigemptyset(sigset);
1515 OUTPUT:
1516 RETVAL
2304df62
AD
1517
1518int
1519sigismember(sigset, sig)
1520 POSIX::SigSet sigset
1521 int sig
1522
a0d0e21e
LW
1523MODULE = Termios PACKAGE = POSIX::Termios PREFIX = cf
1524
11a39fe4 1525void
a0d0e21e 1526new(packname = "POSIX::Termios", ...)
d3f5e399 1527 const char * packname
a0d0e21e
LW
1528 CODE:
1529 {
1530#ifdef I_TERMIOS
a2261f90
NC
1531 void *const p = allocate_struct(aTHX_ (ST(0) = sv_newmortal()),
1532 sizeof(struct termios), packname);
11a39fe4
NC
1533 /* The previous implementation stored a pointer to an uninitialised
1534 struct termios. Seems safer to initialise it, particularly as
1535 this implementation exposes the struct to prying from perl-space.
1536 */
a2261f90 1537 memset(p, 0, 1 + sizeof(struct termios));
11a39fe4 1538 XSRETURN(1);
a0d0e21e
LW
1539#else
1540 not_here("termios");
1541#endif
1542 }
a0d0e21e
LW
1543
1544SysRet
1545getattr(termios_ref, fd = 0)
1546 POSIX::Termios termios_ref
1547 int fd
1548 CODE:
1549 RETVAL = tcgetattr(fd, termios_ref);
1550 OUTPUT:
1551 RETVAL
1552
e08f19f5
TC
1553# If we define TCSANOW here then both a found and not found constant sub
1554# are created causing a Constant subroutine TCSANOW redefined warning
518487b2 1555#ifndef TCSANOW
e08f19f5
TC
1556# define DEF_SETATTR_ACTION 0
1557#else
1558# define DEF_SETATTR_ACTION TCSANOW
518487b2 1559#endif
a0d0e21e 1560SysRet
e08f19f5 1561setattr(termios_ref, fd = 0, optional_actions = DEF_SETATTR_ACTION)
a0d0e21e
LW
1562 POSIX::Termios termios_ref
1563 int fd
1564 int optional_actions
1565 CODE:
518487b2
NC
1566 /* The second argument to the call is mandatory, but we'd like to give
1567 it a useful default. 0 isn't valid on all operating systems - on
1568 Solaris (at least) TCSANOW, TCSADRAIN and TCSAFLUSH have the same
1569 values as the equivalent ioctls, TCSETS, TCSETSW and TCSETSF. */
a0d0e21e
LW
1570 RETVAL = tcsetattr(fd, optional_actions, termios_ref);
1571 OUTPUT:
1572 RETVAL
1573
1574speed_t
2a59a32c 1575getispeed(termios_ref)
a0d0e21e 1576 POSIX::Termios termios_ref
2a59a32c
NC
1577 ALIAS:
1578 getospeed = 1
a0d0e21e 1579 CODE:
2a59a32c 1580 RETVAL = ix ? cfgetospeed(termios_ref) : cfgetispeed(termios_ref);
a0d0e21e
LW
1581 OUTPUT:
1582 RETVAL
1583
1584tcflag_t
2a59a32c 1585getiflag(termios_ref)
a0d0e21e 1586 POSIX::Termios termios_ref
2a59a32c
NC
1587 ALIAS:
1588 getoflag = 1
1589 getcflag = 2
1590 getlflag = 3
a0d0e21e
LW
1591 CODE:
1592#ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
2a59a32c
NC
1593 switch(ix) {
1594 case 0:
1595 RETVAL = termios_ref->c_iflag;
1596 break;
1597 case 1:
1598 RETVAL = termios_ref->c_oflag;
1599 break;
1600 case 2:
1601 RETVAL = termios_ref->c_cflag;
1602 break;
1603 case 3:
1604 RETVAL = termios_ref->c_lflag;
1605 break;
df164f52
DM
1606 default:
1607 RETVAL = 0; /* silence compiler warning */
2a59a32c 1608 }
a0d0e21e 1609#else
2a59a32c
NC
1610 not_here(GvNAME(CvGV(cv)));
1611 RETVAL = 0;
a0d0e21e
LW
1612#endif
1613 OUTPUT:
1614 RETVAL
1615
1616cc_t
1617getcc(termios_ref, ccix)
1618 POSIX::Termios termios_ref
b56fc9ec 1619 unsigned int ccix
a0d0e21e
LW
1620 CODE:
1621#ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
1622 if (ccix >= NCCS)
1623 croak("Bad getcc subscript");
1624 RETVAL = termios_ref->c_cc[ccix];
1625#else
640cc986
HM
1626 not_here("getcc");
1627 RETVAL = 0;
a0d0e21e
LW
1628#endif
1629 OUTPUT:
1630 RETVAL
1631
1632SysRet
2a59a32c 1633setispeed(termios_ref, speed)
a0d0e21e
LW
1634 POSIX::Termios termios_ref
1635 speed_t speed
2a59a32c
NC
1636 ALIAS:
1637 setospeed = 1
a0d0e21e 1638 CODE:
2a59a32c
NC
1639 RETVAL = ix
1640 ? cfsetospeed(termios_ref, speed) : cfsetispeed(termios_ref, speed);
1641 OUTPUT:
1642 RETVAL
a0d0e21e
LW
1643
1644void
2a59a32c 1645setiflag(termios_ref, flag)
a0d0e21e 1646 POSIX::Termios termios_ref
2a59a32c
NC
1647 tcflag_t flag
1648 ALIAS:
1649 setoflag = 1
1650 setcflag = 2
1651 setlflag = 3
a0d0e21e
LW
1652 CODE:
1653#ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
2a59a32c
NC
1654 switch(ix) {
1655 case 0:
1656 termios_ref->c_iflag = flag;
1657 break;
1658 case 1:
1659 termios_ref->c_oflag = flag;
1660 break;
1661 case 2:
1662 termios_ref->c_cflag = flag;
1663 break;
1664 case 3:
1665 termios_ref->c_lflag = flag;
1666 break;
1667 }
a0d0e21e 1668#else
2a59a32c 1669 not_here(GvNAME(CvGV(cv)));
a0d0e21e
LW
1670#endif
1671
1672void
1673setcc(termios_ref, ccix, cc)
1674 POSIX::Termios termios_ref
b56fc9ec 1675 unsigned int ccix
a0d0e21e
LW
1676 cc_t cc
1677 CODE:
1678#ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
1679 if (ccix >= NCCS)
1680 croak("Bad setcc subscript");
1681 termios_ref->c_cc[ccix] = cc;
1682#else
1683 not_here("setcc");
1684#endif
1685
1686
a0d0e21e
LW
1687MODULE = POSIX PACKAGE = POSIX
1688
1cb0fb50 1689INCLUDE: const-xs.inc
a290f238 1690
e99d581a
NC
1691int
1692WEXITSTATUS(status)
1693 int status
72bfe1b2
NC
1694 ALIAS:
1695 POSIX::WIFEXITED = 1
1696 POSIX::WIFSIGNALED = 2
1697 POSIX::WIFSTOPPED = 3
1698 POSIX::WSTOPSIG = 4
1699 POSIX::WTERMSIG = 5
1700 CODE:
fabb67aa
SK
1701#if !defined(WEXITSTATUS) || !defined(WIFEXITED) || !defined(WIFSIGNALED) \
1702 || !defined(WIFSTOPPED) || !defined(WSTOPSIG) || !defined(WTERMSIG)
19c4478c
NC
1703 RETVAL = 0; /* Silence compilers that notice this, but don't realise
1704 that not_here() can't return. */
1705#endif
72bfe1b2
NC
1706 switch(ix) {
1707 case 0:
d49025b7 1708#ifdef WEXITSTATUS
17028706 1709 RETVAL = WEXITSTATUS(WMUNGE(status));
d49025b7
NC
1710#else
1711 not_here("WEXITSTATUS");
1712#endif
72bfe1b2
NC
1713 break;
1714 case 1:
d49025b7 1715#ifdef WIFEXITED
17028706 1716 RETVAL = WIFEXITED(WMUNGE(status));
d49025b7
NC
1717#else
1718 not_here("WIFEXITED");
1719#endif
72bfe1b2
NC
1720 break;
1721 case 2:
d49025b7 1722#ifdef WIFSIGNALED
17028706 1723 RETVAL = WIFSIGNALED(WMUNGE(status));
d49025b7
NC
1724#else
1725 not_here("WIFSIGNALED");
1726#endif
72bfe1b2
NC
1727 break;
1728 case 3:
d49025b7 1729#ifdef WIFSTOPPED
17028706 1730 RETVAL = WIFSTOPPED(WMUNGE(status));
d49025b7
NC
1731#else
1732 not_here("WIFSTOPPED");
1733#endif
72bfe1b2
NC
1734 break;
1735 case 4:
d49025b7 1736#ifdef WSTOPSIG
17028706 1737 RETVAL = WSTOPSIG(WMUNGE(status));
d49025b7
NC
1738#else
1739 not_here("WSTOPSIG");
1740#endif
72bfe1b2
NC
1741 break;
1742 case 5:
d49025b7 1743#ifdef WTERMSIG
17028706 1744 RETVAL = WTERMSIG(WMUNGE(status));
d49025b7
NC
1745#else
1746 not_here("WTERMSIG");
1747#endif
72bfe1b2
NC
1748 break;
1749 default:
c33e8be1 1750 Perl_croak(aTHX_ "Illegal alias %d for POSIX::W*", (int)ix);
72bfe1b2
NC
1751 }
1752 OUTPUT:
1753 RETVAL
2304df62 1754
2304df62
AD
1755SysRet
1756open(filename, flags = O_RDONLY, mode = 0666)
1757 char * filename
1758 int flags
a0d0e21e 1759 Mode_t mode
748a9306
LW
1760 CODE:
1761 if (flags & (O_APPEND|O_CREAT|O_TRUNC|O_RDWR|O_WRONLY|O_EXCL))
1762 TAINT_PROPER("open");
1763 RETVAL = open(filename, flags, mode);
1764 OUTPUT:
1765 RETVAL
1766
2304df62
AD
1767
1768HV *
1769localeconv()
1770 CODE:
3f3bcbfc
KW
1771#ifndef HAS_LOCALECONV
1772 localeconv(); /* A stub to call not_here(). */
1773#else
2304df62 1774 struct lconv *lcbuf;
a835cd47
KW
1775
1776 /* localeconv() deals with both LC_NUMERIC and LC_MONETARY, but
1777 * LC_MONETARY is already in the correct locale */
1778 STORE_NUMERIC_STANDARD_FORCE_LOCAL();
1779
2304df62 1780 RETVAL = newHV();
c4e79b56 1781 sv_2mortal((SV*)RETVAL);
8063af02 1782 if ((lcbuf = localeconv())) {
2f0945cb
NC
1783 const struct lconv_offset *strings = lconv_strings;
1784 const struct lconv_offset *integers = lconv_integers;
1785 const char *ptr = (const char *) lcbuf;
1786
1787 do {
c1284011
KW
1788 /* This string may be controlled by either LC_NUMERIC, or
1789 * LC_MONETARY */
1790 bool is_utf8_locale
1791#if defined(USE_LOCALE_NUMERIC) && defined(USE_LOCALE_MONETARY)
1792 = _is_cur_LC_category_utf8((isLC_NUMERIC_STRING(strings->name))
1793 ? LC_NUMERIC
1794 : LC_MONETARY);
1795#elif defined(USE_LOCALE_NUMERIC)
1796 = _is_cur_LC_category_utf8(LC_NUMERIC);
1797#elif defined(USE_LOCALE_MONETARY)
1798 = _is_cur_LC_category_utf8(LC_MONETARY);
1799#else
1800 = FALSE;
1801#endif
1802
2f0945cb
NC
1803 const char *value = *((const char **)(ptr + strings->offset));
1804
c1284011
KW
1805 if (value && *value) {
1806 (void) hv_store(RETVAL,
1807 strings->name,
1808 strlen(strings->name),
1809 newSVpvn_utf8(value,
1810 strlen(value),
1811
1812 /* We mark it as UTF-8 if a utf8 locale
1813 * and is valid, non-ascii UTF-8 */
1814 is_utf8_locale
1815 && ! is_ascii_string((U8 *) value, 0)
1816 && is_utf8_string((U8 *) value, 0)),
1817 0);
1818 }
2f0945cb
NC
1819 } while ((++strings)->name);
1820
1821 do {
1822 const char value = *((const char *)(ptr + integers->offset));
1823
1824 if (value != CHAR_MAX)
1825 (void) hv_store(RETVAL, integers->name,
1826 strlen(integers->name), newSViv(value), 0);
1827 } while ((++integers)->name);
2304df62 1828 }
a835cd47 1829 RESTORE_NUMERIC_STANDARD();
3f3bcbfc 1830#endif /* HAS_LOCALECONV */
2304df62
AD
1831 OUTPUT:
1832 RETVAL
1833
1834char *
c28ee57b 1835setlocale(category, locale = 0)
2304df62 1836 int category
8e70cf7a 1837 const char * locale
1ba01ae3
SH
1838 PREINIT:
1839 char * retval;
c28ee57b 1840 CODE:
49efabc8
KW
1841#ifdef USE_LOCALE_NUMERIC
1842 /* A 0 (or NULL) locale means only query what the current one is. We
1843 * have the LC_NUMERIC name saved, because we are normally switched
1844 * into the C locale for it. Switch back so an LC_ALL query will yield
1845 * the correct results; all other categories don't require special
1846 * handling */
1847 if (locale == 0) {
1848 if (category == LC_NUMERIC) {
1849 XSRETURN_PV(PL_numeric_name);
1850 }
1851# ifdef LC_ALL
1852 else if (category == LC_ALL) {
1853 SET_NUMERIC_LOCAL();
1854 }
1855# endif
1856 }
1857#endif
b385bb4d
KW
1858#ifdef WIN32 /* Use wrapper on Windows */
1859 retval = Perl_my_setlocale(aTHX_ category, locale);
1860#else
1ba01ae3 1861 retval = setlocale(category, locale);
b385bb4d 1862#endif
fbd840df 1863 if (! retval) {
49efabc8
KW
1864 /* Should never happen that a query would return an error, but be
1865 * sure and reset to C locale */
1866 if (locale == 0) {
1867 SET_NUMERIC_STANDARD();
1868 }
fbd840df
KW
1869 XSRETURN_UNDEF;
1870 }
49efabc8
KW
1871
1872 /* Save retval since subsequent setlocale() calls may overwrite it. */
1873 retval = savepv(retval);
1874
1875 /* For locale == 0, we may have switched to NUMERIC_LOCAL. Switch back
1876 * */
1877 if (locale == 0) {
1878 SET_NUMERIC_STANDARD();
1879 XSRETURN_PV(retval);
1880 }
fbd840df 1881 else {
49efabc8 1882 RETVAL = retval;
36477c24 1883#ifdef USE_LOCALE_CTYPE
bbce6d69 1884 if (category == LC_CTYPE
1885#ifdef LC_ALL
1886 || category == LC_ALL
1887#endif
1888 )
1889 {
1890 char *newctype;
1891#ifdef LC_ALL
1892 if (category == LC_ALL)
1893 newctype = setlocale(LC_CTYPE, NULL);
1894 else
1895#endif
1896 newctype = RETVAL;
864dbfa3 1897 new_ctype(newctype);
bbce6d69 1898 }
36477c24 1899#endif /* USE_LOCALE_CTYPE */
1900#ifdef USE_LOCALE_COLLATE
bbce6d69 1901 if (category == LC_COLLATE
1902#ifdef LC_ALL
1903 || category == LC_ALL
1904#endif
1905 )
1906 {
1907 char *newcoll;
1908#ifdef LC_ALL
1909 if (category == LC_ALL)
1910 newcoll = setlocale(LC_COLLATE, NULL);
1911 else
1912#endif
1913 newcoll = RETVAL;
864dbfa3 1914 new_collate(newcoll);
bbce6d69 1915 }
36477c24 1916#endif /* USE_LOCALE_COLLATE */
1917#ifdef USE_LOCALE_NUMERIC
bbce6d69 1918 if (category == LC_NUMERIC
1919#ifdef LC_ALL
1920 || category == LC_ALL
1921#endif
1922 )
1923 {
1924 char *newnum;
1925#ifdef LC_ALL
1926 if (category == LC_ALL)
1927 newnum = setlocale(LC_NUMERIC, NULL);
1928 else
1929#endif
1930 newnum = RETVAL;
864dbfa3 1931 new_numeric(newnum);
bbce6d69 1932 }
36477c24 1933#endif /* USE_LOCALE_NUMERIC */
bbce6d69 1934 }
c28ee57b
JH
1935 OUTPUT:
1936 RETVAL
1ba01ae3 1937 CLEANUP:
fbd840df 1938 Safefree(RETVAL);
2304df62 1939
e1ca407b 1940NV
2304df62 1941acos(x)
e1ca407b 1942 NV x
b256643b 1943 ALIAS:
7965edec
JH
1944 acosh = 1
1945 asin = 2
1946 asinh = 3
1947 atan = 4
1948 atanh = 5
1949 cbrt = 6
1950 ceil = 7
1951 cosh = 8
1952 erf = 9
1953 erfc = 10
1954 exp2 = 11
1955 expm1 = 12
1956 floor = 13
1957 j0 = 14
1958 j1 = 15
1959 lgamma = 16
1960 log10 = 17
1961 log1p = 18
1962 log2 = 19
1963 logb = 20
1964 nearbyint = 21
1965 rint = 22
1966 round = 23
1967 sinh = 24
1968 tan = 25
1969 tanh = 26
1970 tgamma = 27
1971 trunc = 28
1972 y0 = 29
1973 y1 = 30
b256643b 1974 CODE:
78a0541a 1975 RETVAL = NV_NAN;
b256643b
NC
1976 switch (ix) {
1977 case 0:
8a00eddc 1978 RETVAL = Perl_acos(x); /* C89 math */
b256643b
NC
1979 break;
1980 case 1:
5716d070 1981#ifdef c99_acosh
7965edec 1982 RETVAL = c99_acosh(x);
5716d070
JH
1983#else
1984 not_here("acosh");
1985#endif
b256643b
NC
1986 break;
1987 case 2:
8a00eddc 1988 RETVAL = Perl_asin(x); /* C89 math */
b256643b
NC
1989 break;
1990 case 3:
5716d070 1991#ifdef c99_asinh
7965edec 1992 RETVAL = c99_asinh(x);
5716d070
JH
1993#else
1994 not_here("asinh");
1995#endif
b256643b
NC
1996 break;
1997 case 4:
8a00eddc 1998 RETVAL = Perl_atan(x); /* C89 math */
b256643b
NC
1999 break;
2000 case 5:
5716d070 2001#ifdef c99_atanh
7965edec 2002 RETVAL = c99_atanh(x);
5716d070
JH
2003#else
2004 not_here("atanh");
2005#endif
b256643b
NC
2006 break;
2007 case 6:
5716d070 2008#ifdef c99_cbrt
7965edec 2009 RETVAL = c99_cbrt(x);
5716d070
JH
2010#else
2011 not_here("cbrt");
2012#endif
b256643b
NC
2013 break;
2014 case 7:
8a00eddc 2015 RETVAL = Perl_ceil(x); /* C89 math */
b256643b
NC
2016 break;
2017 case 8:
8a00eddc 2018 RETVAL = Perl_cosh(x); /* C89 math */
7965edec
JH
2019 break;
2020 case 9:
5716d070 2021#ifdef c99_erf
7965edec 2022 RETVAL = c99_erf(x);
5716d070
JH
2023#else
2024 not_here("erf");
2025#endif
7965edec
JH
2026 break;
2027 case 10:
5716d070 2028#ifdef c99_erfc
d5799f37 2029 RETVAL = c99_erfc(x);
5716d070
JH
2030#else
2031 not_here("erfc");
2032#endif
7965edec
JH
2033 break;
2034 case 11:
5716d070 2035#ifdef c99_exp2
7965edec 2036 RETVAL = c99_exp2(x);
5716d070
JH
2037#else
2038 not_here("exp2");
2039#endif
7965edec
JH
2040 break;
2041 case 12:
5716d070 2042#ifdef c99_expm1
7965edec 2043 RETVAL = c99_expm1(x);
5716d070
JH
2044#else
2045 not_here("expm1");
2046#endif
7965edec
JH
2047 break;
2048 case 13:
8a00eddc 2049 RETVAL = Perl_floor(x); /* C89 math */
7965edec
JH
2050 break;
2051 case 14:
5716d070 2052#ifdef bessel_j0
7965edec 2053 RETVAL = bessel_j0(x);
5716d070 2054#else
85c93440 2055 not_here("j0");
5716d070 2056#endif
7965edec
JH
2057 break;
2058 case 15:
5716d070 2059#ifdef bessel_j1
7965edec 2060 RETVAL = bessel_j1(x);
5716d070 2061#else
85c93440 2062 not_here("j1");
5716d070 2063#endif
7965edec
JH
2064 break;
2065 case 16:
d334ccbe
JH
2066 /* XXX lgamma_r -- the lgamma accesses a global variable (signgam),
2067 * which is evil. Some platforms have lgamma_r, which has
2068 * extra parameter instead of the global variable. */
5716d070 2069#ifdef c99_lgamma
7965edec 2070 RETVAL = c99_lgamma(x);
5716d070
JH
2071#else
2072 not_here("lgamma");
2073#endif
7965edec
JH
2074 break;
2075 case 17:
5716d070 2076 RETVAL = log10(x); /* C89 math */
7965edec
JH
2077 break;
2078 case 18:
5716d070 2079#ifdef c99_log1p
7965edec 2080 RETVAL = c99_log1p(x);
5716d070
JH
2081#else
2082 not_here("log1p");
2083#endif
7965edec
JH
2084 break;
2085 case 19:
5716d070 2086#ifdef c99_log2
7965edec 2087 RETVAL = c99_log2(x);
5716d070
JH
2088#else
2089 not_here("log2");
2090#endif
7965edec
JH
2091 break;
2092 case 20:
5716d070 2093#ifdef c99_logb
7965edec 2094 RETVAL = c99_logb(x);
5716d070
JH
2095#else
2096 not_here("logb");
2097#endif
7965edec
JH
2098 break;
2099 case 21:
5716d070 2100#ifdef c99_nearbyint
7965edec 2101 RETVAL = c99_nearbyint(x);
5716d070
JH
2102#else
2103 not_here("nearbyint");
2104#endif
7965edec
JH
2105 break;
2106 case 22:
5716d070 2107#ifdef c99_rint
7965edec 2108 RETVAL = c99_rint(x);
5716d070
JH
2109#else
2110 not_here("rint");
2111#endif
7965edec
JH
2112 break;
2113 case 23:
5716d070 2114#ifdef c99_round
7965edec 2115 RETVAL = c99_round(x);
5716d070
JH
2116#else
2117 not_here("round");
2118#endif
7965edec
JH
2119 break;
2120 case 24:
8a00eddc 2121 RETVAL = Perl_sinh(x); /* C89 math */
7965edec
JH
2122 break;
2123 case 25:
8a00eddc 2124 RETVAL = Perl_tan(x); /* C89 math */
b256643b 2125 break;
7965edec 2126 case 26:
8a00eddc 2127 RETVAL = Perl_tanh(x); /* C89 math */
7965edec
JH
2128 break;
2129 case 27:
d334ccbe
JH
2130 /* XXX tgamma_r -- the lgamma accesses a global variable (signgam),
2131 * which is evil. Some platforms have tgamma_r, which has
2132 * extra parameter instead of the global variable. */
5716d070 2133#ifdef c99_tgamma
7965edec 2134 RETVAL = c99_tgamma(x);
5716d070
JH
2135#else
2136 not_here("tgamma");
2137#endif
7965edec
JH
2138 break;
2139 case 28:
5716d070 2140#ifdef c99_trunc
7965edec 2141 RETVAL = c99_trunc(x);
5716d070
JH
2142#else
2143 not_here("trunc");
2144#endif
7965edec
JH
2145 break;
2146 case 29:
5716d070 2147#ifdef bessel_y0
7965edec 2148 RETVAL = bessel_y0(x);
5716d070 2149#else
85c93440 2150 not_here("y0");
5716d070 2151#endif
7965edec
JH
2152 break;
2153 case 30:
2154 default:
5716d070 2155#ifdef bessel_y1
7965edec 2156 RETVAL = bessel_y1(x);
5716d070 2157#else
85c93440 2158 not_here("y1");
5716d070 2159#endif
7965edec
JH
2160 }
2161 OUTPUT:
2162 RETVAL
2163
2164IV
a5713e21
JH
2165fegetround()
2166 CODE:
78a0541a 2167#ifdef HAS_FEGETROUND
d5f4f26a 2168 RETVAL = my_fegetround();
78a0541a
JH
2169#else
2170 RETVAL = -1;
a5713e21
JH
2171 not_here("fegetround");
2172#endif
2173 OUTPUT:
2174 RETVAL
2175
2176IV
2177fesetround(x)
2178 IV x
2179 CODE:
2180#ifdef HAS_FEGETROUND /* canary for fesetround */
2181 RETVAL = fesetround(x);
879d23d2 2182#elif defined(HAS_FPGETROUND) /* canary for fpsetround */
e0939537 2183 switch (x) {
e0939537
JH
2184 case FE_TONEAREST: RETVAL = fpsetround(FP_RN); break;
2185 case FE_TOWARDZERO: RETVAL = fpsetround(FP_RZ); break;
2186 case FE_DOWNWARD: RETVAL = fpsetround(FP_RM); break;
2187 case FE_UPWARD: RETVAL = fpsetround(FP_RP); break;
ebac59ac 2188 default: RETVAL = -1; break;
e0939537 2189 }
877206df
JH
2190#elif defined(__osf__) /* Tru64 */
2191 switch (x) {
2192 case FE_TONEAREST: RETVAL = write_rnd(FP_RND_RN); break;
2193 case FE_TOWARDZERO: RETVAL = write_rnd(FP_RND_RZ); break;
2194 case FE_DOWNWARD: RETVAL = write_rnd(FP_RND_RM); break;
2195 case FE_UPWARD: RETVAL = write_rnd(FP_RND_RP); break;
2196 default: RETVAL = -1; break;
2197 }
a5713e21 2198#else
78a0541a 2199 RETVAL = -1;
a5713e21
JH
2200 not_here("fesetround");
2201#endif
2202 OUTPUT:
2203 RETVAL
2204
2205IV
7965edec
JH
2206fpclassify(x)
2207 NV x
2208 ALIAS:
2209 ilogb = 1
2210 isfinite = 2
2211 isinf = 3
2212 isnan = 4
2213 isnormal = 5
d5f4f26a 2214 lrint = 6
9e010b89
JH
2215 lround = 7
2216 signbit = 8
7965edec 2217 CODE:
78a0541a 2218 RETVAL = -1;
7965edec
JH
2219 switch (ix) {
2220 case 0:
5716d070 2221#ifdef c99_fpclassify
7965edec 2222 RETVAL = c99_fpclassify(x);
5716d070
JH
2223#else
2224 not_here("fpclassify");
2225#endif
7965edec
JH
2226 break;
2227 case 1:
5716d070 2228#ifdef c99_ilogb
7965edec 2229 RETVAL = c99_ilogb(x);
5716d070
JH
2230#else
2231 not_here("ilogb");
2232#endif
7965edec
JH
2233 break;
2234 case 2:
2235 RETVAL = Perl_isfinite(x);
2236 break;
2237 case 3:
2238 RETVAL = Perl_isinf(x);
2239 break;
2240 case 4:
2241 RETVAL = Perl_isnan(x);
2242 break;
2243 case 5:
5716d070 2244#ifdef c99_isnormal
7965edec 2245 RETVAL = c99_isnormal(x);
5716d070
JH
2246#else
2247 not_here("isnormal");
2248#endif
7965edec
JH
2249 break;
2250 case 6:
d5f4f26a
JH
2251#ifdef c99_lrint
2252 RETVAL = c99_lrint(x);
2253#else
2254 not_here("lrint");
2255#endif
2256 break;
2257 case 7:
9e010b89
JH
2258#ifdef c99_lround
2259 RETVAL = c99_lround(x);
2260#else
2261 not_here("lround");
2262#endif
2263 break;
2264 case 8:
7965edec 2265 default:
5716d070
JH
2266#ifdef Perl_signbit
2267 RETVAL = Perl_signbit(x);
2268#endif
7965edec 2269 break;
b256643b
NC
2270 }
2271 OUTPUT:
2272 RETVAL
2304df62 2273
e1ca407b 2274NV
7965edec 2275copysign(x,y)
e1ca407b
A
2276 NV x
2277 NV y
7965edec
JH
2278 ALIAS:
2279 fdim = 1
2280 fmax = 2
2281 fmin = 3
2282 fmod = 4
2283 hypot = 5
2284 isgreater = 6
2285 isgreaterequal = 7
2286 isless = 8
2287 islessequal = 9
2288 islessgreater = 10
2289 isunordered = 11
2290 nextafter = 12
2291 nexttoward = 13
2292 remainder = 14
2293 CODE:
78a0541a 2294 RETVAL = NV_NAN;
7965edec
JH
2295 switch (ix) {
2296 case 0:
5716d070 2297#ifdef c99_copysign
7965edec 2298 RETVAL = c99_copysign(x, y);
5716d070
JH
2299#else
2300 not_here("copysign");
2301#endif
7965edec
JH
2302 break;
2303 case 1:
5716d070 2304#ifdef c99_fdim
7965edec 2305 RETVAL = c99_fdim(x, y);
5716d070
JH
2306#else
2307 not_here("fdim");
2308#endif
7965edec
JH
2309 break;
2310 case 2:
5716d070 2311#ifdef c99_fmax
7965edec 2312 RETVAL = c99_fmax(x, y);
5716d070
JH
2313#else
2314 not_here("fmax");
2315#endif
7965edec
JH
2316 break;
2317 case 3:
5716d070 2318#ifdef c99_fmin
7965edec 2319 RETVAL = c99_fmin(x, y);
5716d070
JH
2320#else
2321 not_here("fmin");
2322#endif
7965edec
JH
2323 break;
2324 case 4:
8a00eddc 2325 RETVAL = Perl_fmod(x, y); /* C89 math */
7965edec
JH
2326 break;
2327 case 5:
5716d070 2328#ifdef c99_hypot
7965edec 2329 RETVAL = c99_hypot(x, y);
5716d070
JH
2330#else
2331 not_here("hypot");
2332#endif
7965edec
JH
2333 break;
2334 case 6:
5716d070 2335#ifdef c99_isgreater
7965edec 2336 RETVAL = c99_isgreater(x, y);
5716d070
JH
2337#else
2338 not_here("isgreater");
2339#endif
7965edec
JH
2340 break;
2341 case 7:
5716d070 2342#ifdef c99_isgreaterequal
7965edec 2343 RETVAL = c99_isgreaterequal(x, y);
5716d070
JH
2344#else
2345 not_here("isgreaterequal");
2346#endif
7965edec
JH
2347 break;
2348 case 8:
5716d070 2349#ifdef c99_isless
7965edec 2350 RETVAL = c99_isless(x, y);
5716d070
JH
2351#else
2352 not_here("isless");
2353#endif
7965edec
JH
2354 break;
2355 case 9:
5716d070 2356#ifdef c99_islessequal
7965edec 2357 RETVAL = c99_islessequal(x, y);
5716d070
JH
2358#else
2359 not_here("islessequal");
2360#endif
7965edec
JH
2361 break;
2362 case 10:
5716d070 2363#ifdef c99_islessgreater
7965edec 2364 RETVAL = c99_islessgreater(x, y);
5716d070
JH
2365#else
2366 not_here("islessgreater");
2367#endif
7965edec
JH
2368 break;
2369 case 11:
5716d070 2370#ifdef c99_isunordered
7965edec 2371 RETVAL = c99_isunordered(x, y);
5716d070
JH
2372#else
2373 not_here("isunordered");
2374#endif
7965edec
JH
2375 break;
2376 case 12:
5716d070 2377#ifdef c99_nextafter
7965edec 2378 RETVAL = c99_nextafter(x, y);
5716d070
JH
2379#else
2380 not_here("nextafter");
2381#endif
7965edec
JH
2382 break;
2383 case 13:
5716d070 2384#ifdef c99_nexttoward
7965edec 2385 RETVAL = c99_nexttoward(x, y);
5716d070
JH
2386#else
2387 not_here("nexttoward");
2388#endif
7965edec
JH
2389 break;
2390 case 14:
2391 default:
5716d070 2392#ifdef c99_remainder
7965edec 2393 RETVAL = c99_remainder(x, y);
5716d070
JH
2394#else
2395 not_here("remainder");
2396#endif
7965edec
JH
2397 break;
2398 }
2399 OUTPUT:
2400 RETVAL
2304df62
AD
2401
2402void
2403frexp(x)
e1ca407b 2404 NV x
2304df62
AD
2405 PPCODE:
2406 int expvar;
2304df62 2407 /* (We already know stack is long enough.) */
5716d070 2408 PUSHs(sv_2mortal(newSVnv(Perl_frexp(x,&expvar)))); /* C89 math */
2304df62
AD
2409 PUSHs(sv_2mortal(newSViv(expvar)));
2410
e1ca407b 2411NV
2304df62 2412ldexp(x,exp)
e1ca407b 2413 NV x
2304df62
AD
2414 int exp
2415
2304df62
AD
2416void
2417modf(x)
e1ca407b 2418 NV x
2304df62 2419 PPCODE:
e1ca407b 2420 NV intvar;
2304df62 2421 /* (We already know stack is long enough.) */
5716d070 2422 PUSHs(sv_2mortal(newSVnv(Perl_modf(x,&intvar)))); /* C89 math */
2304df62
AD
2423 PUSHs(sv_2mortal(newSVnv(intvar)));
2424
7965edec
JH
2425void
2426remquo(x,y)
2427 NV x
2428 NV y
2429 PPCODE:
5716d070 2430#ifdef c99_remquo
7965edec
JH
2431 int intvar;
2432 PUSHs(sv_2mortal(newSVnv(c99_remquo(x,y,&intvar))));
2433 PUSHs(sv_2mortal(newSVnv(intvar)));
5716d070
JH
2434#else
2435 not_here("remquo");
2436#endif
7965edec
JH
2437
2438NV
2439scalbn(x,y)
2440 NV x
2441 IV y
2442 CODE:
5716d070 2443#ifdef c99_scalbn
7965edec 2444 RETVAL = c99_scalbn(x, y);
5716d070 2445#else
78a0541a 2446 RETVAL = NV_NAN;
5716d070
JH
2447 not_here("scalbn");
2448#endif
7965edec
JH
2449 OUTPUT:
2450 RETVAL
2451
2452NV
2453fma(x,y,z)
2454 NV x
2455 NV y
2456 NV z
2457 CODE:
5716d070 2458#ifdef c99_fma
7965edec 2459 RETVAL = c99_fma(x, y, z);
5716d070 2460#else
78a0541a 2461 RETVAL = NV_NAN;
5716d070
JH
2462 not_here("fma");
2463#endif
7965edec
JH
2464 OUTPUT:
2465 RETVAL
2466
2467NV
b05fd80e 2468nan(s = 0)
7965edec
JH
2469 char* s;
2470 CODE:
5716d070 2471#ifdef c99_nan
b05fd80e 2472 RETVAL = c99_nan(s ? s : "");
7c7d45f1
JH
2473#elif defined(NV_NAN)
2474 /* XXX if s != NULL, warn about unused argument,
2475 * or implement the nan payload setting. */
78a0541a 2476 RETVAL = NV_NAN;
7c7d45f1 2477#else
5716d070
JH
2478 not_here("nan");
2479#endif
7965edec
JH
2480 OUTPUT:
2481 RETVAL
2482
2483NV
2484jn(x,y)
2485 IV x
2486 NV y
2487 ALIAS:
2488 yn = 1
2489 CODE:
78a0541a 2490 RETVAL = NV_NAN;
7965edec
JH
2491 switch (ix) {
2492 case 0:
5716d070 2493#ifdef bessel_jn
7965edec 2494 RETVAL = bessel_jn(x, y);
5716d070
JH
2495#else
2496 not_here("jn");
2497#endif
7965edec
JH
2498 break;
2499 case 1:
2500 default:
5716d070 2501#ifdef bessel_yn
7965edec 2502 RETVAL = bessel_yn(x, y);
5716d070
JH
2503#else
2504 not_here("yn");
2505#endif
7965edec
JH
2506 break;
2507 }
2508 OUTPUT:
2509 RETVAL
2510
2304df62 2511SysRet
1dfe7606 2512sigaction(sig, optaction, oldaction = 0)
2304df62 2513 int sig
1dfe7606 2514 SV * optaction
2304df62
AD
2515 POSIX::SigAction oldaction
2516 CODE:
2986a63f 2517#if defined(WIN32) || defined(NETWARE)
6dead956
GS
2518 RETVAL = not_here("sigaction");
2519#else
2304df62
AD
2520# This code is really grody because we're trying to make the signal
2521# interface look beautiful, which is hard.
2522
2304df62 2523 {
27da23d5 2524 dVAR;
1dfe7606 2525 POSIX__SigAction action;
f584eb2d 2526 GV *siggv = gv_fetchpvs("SIG", GV_ADD, SVt_PVHV);
2304df62
AD
2527 struct sigaction act;
2528 struct sigaction oact;
1dfe7606 2529 sigset_t sset;
183bde56 2530 SV *osset_sv;
27c1a449 2531 sigset_t osset;
2304df62
AD
2532 POSIX__SigSet sigset;
2533 SV** svp;
1d81eac9 2534 SV** sigsvp;
3609ea0d 2535
516d25e8
SP
2536 if (sig < 0) {
2537 croak("Negative signals are not allowed");
2538 }
2539
1d81eac9 2540 if (sig == 0 && SvPOK(ST(0))) {
aa07b2f6 2541 const char *s = SvPVX_const(ST(0));
1d81eac9
JH
2542 int i = whichsig(s);
2543
2544 if (i < 0 && memEQ(s, "SIG", 3))
2545 i = whichsig(s + 3);
2546 if (i < 0) {
2547 if (ckWARN(WARN_SIGNAL))
2548 Perl_warner(aTHX_ packWARN(WARN_SIGNAL),
2549 "No such signal: SIG%s", s);
2550 XSRETURN_UNDEF;
2551 }
2552 else
2553 sig = i;
2554 }
3609ea0d
JH
2555#ifdef NSIG
2556 if (sig > NSIG) { /* NSIG - 1 is still okay. */
2557 Perl_warner(aTHX_ packWARN(WARN_SIGNAL),
2558 "No such signal: %d", sig);
2559 XSRETURN_UNDEF;
2560 }
2561#endif
1d81eac9
JH
2562 sigsvp = hv_fetch(GvHVn(siggv),
2563 PL_sig_name[sig],
2564 strlen(PL_sig_name[sig]),
2565 TRUE);
2304df62 2566
1dfe7606
AJ
2567 /* Check optaction and set action */
2568 if(SvTRUE(optaction)) {
2569 if(sv_isa(optaction, "POSIX::SigAction"))
2570 action = (HV*)SvRV(optaction);
2571 else
2572 croak("action is not of type POSIX::SigAction");
2573 }
2574 else {
2575 action=0;
2576 }
2577
2578 /* sigaction() is supposed to look atomic. In particular, any
2579 * signal handler invoked during a sigaction() call should
2580 * see either the old or the new disposition, and not something
2581 * in between. We use sigprocmask() to make it so.
2582 */
2583 sigfillset(&sset);
2584 RETVAL=sigprocmask(SIG_BLOCK, &sset, &osset);
2585 if(RETVAL == -1)
15c0d34a 2586 XSRETURN_UNDEF;
1dfe7606
AJ
2587 ENTER;
2588 /* Restore signal mask no matter how we exit this block. */
f584eb2d 2589 osset_sv = newSVpvn((char *)(&osset), sizeof(sigset_t));
183bde56 2590 SAVEFREESV( osset_sv );
40b7a5f5 2591 SAVEDESTRUCTOR_X(restore_sigmask, osset_sv);
1dfe7606
AJ
2592
2593 RETVAL=-1; /* In case both oldaction and action are 0. */
2594
2595 /* Remember old disposition if desired. */
2304df62 2596 if (oldaction) {
017a3ce5 2597 svp = hv_fetchs(oldaction, "HANDLER", TRUE);
1dfe7606
AJ
2598 if(!svp)
2599 croak("Can't supply an oldaction without a HANDLER");
2600 if(SvTRUE(*sigsvp)) { /* TBD: what if "0"? */
2601 sv_setsv(*svp, *sigsvp);
2602 }
2603 else {
f584eb2d 2604 sv_setpvs(*svp, "DEFAULT");
1dfe7606
AJ
2605 }
2606 RETVAL = sigaction(sig, (struct sigaction *)0, & oact);
6ca4bbc9
GG
2607 if(RETVAL == -1) {
2608 LEAVE;
15c0d34a 2609 XSRETURN_UNDEF;
6ca4bbc9 2610 }
1dfe7606 2611 /* Get back the mask. */
017a3ce5 2612 svp = hv_fetchs(oldaction, "MASK", TRUE);
1dfe7606 2613 if (sv_isa(*svp, "POSIX::SigSet")) {
92b39396 2614 sigset = (sigset_t *) SvPV_nolen(SvRV(*svp));
1dfe7606
AJ
2615 }
2616 else {
92b39396
NC
2617 sigset = (sigset_t *) allocate_struct(aTHX_ *svp,
2618 sizeof(sigset_t),
2619 "POSIX::SigSet");
1dfe7606
AJ
2620 }
2621 *sigset = oact.sa_mask;
2622
2623 /* Get back the flags. */
017a3ce5 2624 svp = hv_fetchs(oldaction, "FLAGS", TRUE);
1dfe7606 2625 sv_setiv(*svp, oact.sa_flags);
d36b6582
CS
2626
2627 /* Get back whether the old handler used safe signals. */
017a3ce5 2628 svp = hv_fetchs(oldaction, "SAFE", TRUE);
e91e3b10
RB
2629 sv_setiv(*svp,
2630 /* compare incompatible pointers by casting to integer */
2631 PTR2nat(oact.sa_handler) == PTR2nat(PL_csighandlerp));
2304df62
AD
2632 }
2633
2634 if (action) {
d36b6582
CS
2635 /* Safe signals use "csighandler", which vectors through the
2636 PL_sighandlerp pointer when it's safe to do so.
2637 (BTW, "csighandler" is very different from "sighandler".) */
017a3ce5 2638 svp = hv_fetchs(action, "SAFE", FALSE);
e91e3b10
RB
2639 act.sa_handler =
2640 DPTR2FPTR(
87d46f97 2641 void (*)(int),
e91e3b10
RB
2642 (*svp && SvTRUE(*svp))
2643 ? PL_csighandlerp : PL_sighandlerp
2644 );
d36b6582
CS
2645
2646 /* Vector new Perl handler through %SIG.
2647 (The core signal handlers read %SIG to dispatch.) */
017a3ce5 2648 svp = hv_fetchs(action, "HANDLER", FALSE);
2304df62
AD
2649 if (!svp)
2650 croak("Can't supply an action without a HANDLER");
1dfe7606 2651 sv_setsv(*sigsvp, *svp);
d36b6582
CS
2652
2653 /* This call actually calls sigaction() with almost the
2654 right settings, including appropriate interpretation
2655 of DEFAULT and IGNORE. However, why are we doing
2656 this when we're about to do it again just below? XXX */
17cffb37 2657 SvSETMAGIC(*sigsvp);
d36b6582
CS
2658
2659 /* And here again we duplicate -- DEFAULT/IGNORE checking. */
1dfe7606 2660 if(SvPOK(*svp)) {
aa07b2f6 2661 const char *s=SvPVX_const(*svp);
1dfe7606
AJ
2662 if(strEQ(s,"IGNORE")) {
2663 act.sa_handler = SIG_IGN;
2664 }
2665 else if(strEQ(s,"DEFAULT")) {
2666 act.sa_handler = SIG_DFL;
2667 }
1dfe7606 2668 }
2304df62
AD
2669
2670 /* Set up any desired mask. */
017a3ce5 2671 svp = hv_fetchs(action, "MASK", FALSE);
2304df62 2672 if (svp && sv_isa(*svp, "POSIX::SigSet")) {
92b39396 2673 sigset = (sigset_t *) SvPV_nolen(SvRV(*svp));
2304df62
AD
2674 act.sa_mask = *sigset;
2675 }
2676 else
85e6fe83 2677 sigemptyset(& act.sa_mask);
2304df62
AD
2678
2679 /* Set up any desired flags. */
017a3ce5 2680 svp = hv_fetchs(action, "FLAGS", FALSE);
2304df62 2681 act.sa_flags = svp ? SvIV(*svp) : 0;
2304df62 2682
1dfe7606
AJ
2683 /* Don't worry about cleaning up *sigsvp if this fails,
2684 * because that means we tried to disposition a
2685 * nonblockable signal, in which case *sigsvp is
2686 * essentially meaningless anyway.
2687 */
6c418a22 2688 RETVAL = sigaction(sig, & act, (struct sigaction *)0);
6ca4bbc9
GG
2689 if(RETVAL == -1) {
2690 LEAVE;
a7aad5de 2691 XSRETURN_UNDEF;
6ca4bbc9 2692 }
2304df62 2693 }
1dfe7606
AJ
2694
2695 LEAVE;
2304df62 2696 }
6dead956 2697#endif
2304df62
AD
2698 OUTPUT:
2699 RETVAL
2700
2701SysRet
2702sigpending(sigset)
2703 POSIX::SigSet sigset
7a004119
NC
2704 ALIAS:
2705 sigsuspend = 1
2706 CODE:
2707 RETVAL = ix ? sigsuspend(sigset) : sigpending(sigset);
2708 OUTPUT:
2709 RETVAL
20120e59
LT
2710 CLEANUP:
2711 PERL_ASYNC_CHECK();
2304df62
AD
2712
2713SysRet
2714sigprocmask(how, sigset, oldsigset = 0)
2715 int how
b13bbac7 2716 POSIX::SigSet sigset = NO_INIT
33c27489
GS
2717 POSIX::SigSet oldsigset = NO_INIT
2718INIT:
a3b811a7 2719 if (! SvOK(ST(1))) {
b13bbac7 2720 sigset = NULL;
a3b811a7 2721 } else if (sv_isa(ST(1), "POSIX::SigSet")) {
92b39396 2722 sigset = (sigset_t *) SvPV_nolen(SvRV(ST(1)));
b13bbac7
AB
2723 } else {
2724 croak("sigset is not of type POSIX::SigSet");
33c27489 2725 }
b13bbac7 2726
194cfca0 2727 if (items < 3 || ! SvOK(ST(2))) {
b13bbac7 2728 oldsigset = NULL;
a3b811a7 2729 } else if (sv_isa(ST(2), "POSIX::SigSet")) {
92b39396 2730 oldsigset = (sigset_t *) SvPV_nolen(SvRV(ST(2)));
b13bbac7
AB
2731 } else {
2732 croak("oldsigset is not of type POSIX::SigSet");
33c27489 2733 }
2304df62 2734
2304df62
AD
2735void
2736_exit(status)
2737 int status
8990e307 2738
85e6fe83 2739SysRet
8990e307
LW
2740dup2(fd1, fd2)
2741 int fd1
2742 int fd2
ad413e46
NC
2743 CODE:
2744#ifdef WIN32
2745 /* RT #98912 - More Microsoft muppetry - failing to actually implemented
2746 the well known documented POSIX behaviour for a POSIX API.
2747 http://msdn.microsoft.com/en-us/library/8syseb29.aspx */
2748 RETVAL = dup2(fd1, fd2) == -1 ? -1 : fd2;
2749#else
2750 RETVAL = dup2(fd1, fd2);
2751#endif
2752 OUTPUT:
2753 RETVAL
8990e307 2754
4a9d6100 2755SV *
a0d0e21e 2756lseek(fd, offset, whence)
85e6fe83
LW
2757 int fd
2758 Off_t offset
2759 int whence
4a9d6100
GS
2760 CODE:
2761 Off_t pos = PerlLIO_lseek(fd, offset, whence);
2762 RETVAL = sizeof(Off_t) > sizeof(IV)
2763 ? newSVnv((NV)pos) : newSViv((IV)pos);
2764 OUTPUT:
2765 RETVAL
8990e307 2766
c5661c80 2767void
8990e307
LW
2768nice(incr)
2769 int incr
15f0f28a
AE
2770 PPCODE:
2771 errno = 0;
2772 if ((incr = nice(incr)) != -1 || errno == 0) {
2773 if (incr == 0)
d3d34884 2774 XPUSHs(newSVpvs_flags("0 but true", SVs_TEMP));
15f0f28a
AE
2775 else
2776 XPUSHs(sv_2mortal(newSViv(incr)));
2777 }
8990e307 2778
8063af02 2779void
8990e307 2780pipe()
85e6fe83
LW
2781 PPCODE:
2782 int fds[2];
85e6fe83 2783 if (pipe(fds) != -1) {
924508f0 2784 EXTEND(SP,2);
85e6fe83
LW
2785 PUSHs(sv_2mortal(newSViv(fds[0])));
2786 PUSHs(sv_2mortal(newSViv(fds[1])));
2787 }
8990e307 2788
85e6fe83 2789SysRet
a0d0e21e 2790read(fd, buffer, nbytes)
7747499c
TB
2791 PREINIT:
2792 SV *sv_buffer = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
2793 INPUT:
2794 int fd
2795 size_t nbytes
2796 char * buffer = sv_grow( sv_buffer, nbytes+1 );
a0d0e21e 2797 CLEANUP:
7747499c 2798 if (RETVAL >= 0) {
b162af07 2799 SvCUR_set(sv_buffer, RETVAL);
7747499c
TB
2800 SvPOK_only(sv_buffer);
2801 *SvEND(sv_buffer) = '\0';
bbce6d69 2802 SvTAINTED_on(sv_buffer);
7747499c 2803 }
8990e307 2804
85e6fe83 2805SysRet
8990e307 2806setpgid(pid, pgid)
86200d5c
JH
2807 pid_t pid
2808 pid_t pgid
8990e307 2809
86200d5c 2810pid_t
8990e307
LW
2811setsid()
2812
86200d5c 2813pid_t
8990e307
LW
2814tcgetpgrp(fd)
2815 int fd
2816
85e6fe83 2817SysRet
8990e307
LW
2818tcsetpgrp(fd, pgrp_id)
2819 int fd
86200d5c 2820 pid_t pgrp_id
8990e307 2821
8063af02 2822void
8990e307 2823uname()
2304df62 2824 PPCODE:
a0d0e21e 2825#ifdef HAS_UNAME
85e6fe83 2826 struct utsname buf;
85e6fe83 2827 if (uname(&buf) >= 0) {
924508f0 2828 EXTEND(SP, 5);
d3d34884
NC
2829 PUSHs(newSVpvn_flags(buf.sysname, strlen(buf.sysname), SVs_TEMP));
2830 PUSHs(newSVpvn_flags(buf.nodename, strlen(buf.nodename), SVs_TEMP));
2831 PUSHs(newSVpvn_flags(buf.release, strlen(buf.release), SVs_TEMP));
2832 PUSHs(newSVpvn_flags(buf.version, strlen(buf.version), SVs_TEMP));
2833 PUSHs(newSVpvn_flags(buf.machine, strlen(buf.machine), SVs_TEMP));
8990e307 2834 }
a0d0e21e
LW
2835#else
2836 uname((char *) 0); /* A stub to call not_here(). */
2837#endif
8990e307 2838
85e6fe83 2839SysRet
a0d0e21e
LW
2840write(fd, buffer, nbytes)
2841 int fd
2842 char * buffer
2843 size_t nbytes
2844
33f01dd1
SH
2845SV *
2846tmpnam()
2847 PREINIT:
2848 STRLEN i;
2849 int len;
2850 CODE:
c2b90b61 2851 RETVAL = newSVpvs("");
33f01dd1 2852 SvGROW(RETVAL, L_tmpnam);
0fadf2db
JH
2853 /* Yes, we know tmpnam() is bad. So bad that some compilers
2854 * and linkers warn against using it. But it is here for
2855 * completeness. POSIX.pod warns against using it.
2856 *
2857 * Then again, maybe this should be removed at some point.
2858 * No point in enabling dangerous interfaces. */
cae71c5d
TC
2859 if (ckWARN_d(WARN_DEPRECATED)) {
2860 HV *warned = get_hv("POSIX::_warned", GV_ADD | GV_ADDMULTI);
2861 if (! hv_exists(warned, (const char *)&PL_op, sizeof(PL_op))) {
2862 Perl_warner(aTHX_ packWARN(WARN_DEPRECATED), "Calling POSIX::tmpnam() is deprecated");
2863 hv_store(warned, (const char *)&PL_op, sizeof(PL_op), &PL_sv_yes, 0);
2864 }
2865 }
33f01dd1
SH
2866 len = strlen(tmpnam(SvPV(RETVAL, i)));
2867 SvCUR_set(RETVAL, len);
2868 OUTPUT:
2869 RETVAL
a0d0e21e
LW
2870
2871void
2872abort()
2873
2874int
2875mblen(s, n)
2876 char * s
2877 size_t n
2878
2879size_t
2880mbstowcs(s, pwcs, n)
2881 wchar_t * s
2882 char * pwcs
2883 size_t n
2884
2885int
2886mbtowc(pwc, s, n)
2887 wchar_t * pwc
2888 char * s
2889 size_t n
2890
2891int
2892wcstombs(s, pwcs, n)
2893 char * s
2894 wchar_t * pwcs
2895 size_t n
2896
2897int
2898wctomb(s, wchar)
2899 char * s
2900 wchar_t wchar
2901
2902int
2903strcoll(s1, s2)
2904 char * s1
2905 char * s2
2906
a89d8a78
DH
2907void
2908strtod(str)
2909 char * str
2910 PREINIT:
2911 double num;
2912 char *unparsed;
2913 PPCODE:
371d5d44 2914 STORE_NUMERIC_STANDARD_FORCE_LOCAL();
a89d8a78
DH
2915 num = strtod(str, &unparsed);
2916 PUSHs(sv_2mortal(newSVnv(num)));
2917 if (GIMME == G_ARRAY) {
924508f0 2918 EXTEND(SP, 1);
a89d8a78
DH
2919 if (unparsed)
2920 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
2921 else
6b88bc9c 2922 PUSHs(&PL_sv_undef);
a89d8a78 2923 }
371d5d44 2924 RESTORE_NUMERIC_STANDARD();
a89d8a78 2925
0ff7b9da
JH
2926#ifdef HAS_STRTOLD
2927
2928void
2929strtold(str)
2930 char * str
2931 PREINIT:
2932 long double num;
2933 char *unparsed;
2934 PPCODE:
2935 STORE_NUMERIC_STANDARD_FORCE_LOCAL();
2936 num = strtold(str, &unparsed);
2937 PUSHs(sv_2mortal(newSVnv(num)));
2938 if (GIMME == G_ARRAY) {
2939 EXTEND(SP, 1);
2940 if (unparsed)
2941 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
2942 else
2943 PUSHs(&PL_sv_undef);
2944 }
2945 RESTORE_NUMERIC_STANDARD();
2946
2947#endif
2948
a89d8a78
DH
2949void
2950strtol(str, base = 0)
2951 char * str
2952 int base
2953 PREINIT:
2954 long num;
2955 char *unparsed;
2956 PPCODE:
2957 num = strtol(str, &unparsed, base);
42718184
RB
2958#if IVSIZE <= LONGSIZE
2959 if (num < IV_MIN || num > IV_MAX)
a89d8a78 2960 PUSHs(sv_2mortal(newSVnv((double)num)));
42718184
RB
2961 else
2962#endif
2963 PUSHs(sv_2mortal(newSViv((IV)num)));
a89d8a78 2964 if (GIMME == G_ARRAY) {
924508f0 2965 EXTEND(SP, 1);
a89d8a78
DH
2966 if (unparsed)
2967 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
2968 else
6b88bc9c 2969 PUSHs(&PL_sv_undef);
a89d8a78
DH
2970 }
2971
2972void
2973strtoul(str, base = 0)
4b48cf39 2974 const char * str
a89d8a78
DH
2975 int base
2976 PREINIT:
2977 unsigned long num;
2978 char *unparsed;
2979 PPCODE:
2980 num = strtoul(str, &unparsed, base);
84c133a0
RB
2981#if IVSIZE <= LONGSIZE
2982 if (num > IV_MAX)
a89d8a78 2983 PUSHs(sv_2mortal(newSVnv((double)num)));
84c133a0
RB
2984 else
2985#endif
2986 PUSHs(sv_2mortal(newSViv((IV)num)));
a89d8a78 2987 if (GIMME == G_ARRAY) {
924508f0 2988 EXTEND(SP, 1);
a89d8a78
DH
2989 if (unparsed)
2990 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
2991 else
6b88bc9c 2992 PUSHs(&PL_sv_undef);
a89d8a78
DH
2993 }
2994
8063af02 2995void
a0d0e21e
LW
2996strxfrm(src)
2997 SV * src
85e6fe83 2998 CODE:
a0d0e21e
LW
2999 {
3000 STRLEN srclen;
3001 STRLEN dstlen;
6ec5f825 3002 STRLEN buflen;
a0d0e21e
LW
3003 char *p = SvPV(src,srclen);
3004 srclen++;
6ec5f825
TC
3005 buflen = srclen * 4 + 1;
3006 ST(0) = sv_2mortal(newSV(buflen));
3007 dstlen = strxfrm(SvPVX(ST(0)), p, (size_t)buflen);
3008 if (dstlen >= buflen) {
a0d0e21e
LW
3009 dstlen++;
3010 SvGROW(ST(0), dstlen);
3011 strxfrm(SvPVX(ST(0)), p, (size_t)dstlen);
3012 dstlen--;
3013 }
b162af07 3014 SvCUR_set(ST(0), dstlen);
a0d0e21e
LW
3015 SvPOK_only(ST(0));
3016 }
3017
3018SysRet
3019mkfifo(filename, mode)
3020 char * filename
3021 Mode_t mode
b5890904
NC
3022 ALIAS:
3023 access = 1
748a9306 3024 CODE:
b5890904
NC
3025 if(ix) {
3026 RETVAL = access(filename, mode);
3027 } else {
3028 TAINT_PROPER("mkfifo");
3029 RETVAL = mkfifo(filename, mode);
3030 }
748a9306
LW
3031 OUTPUT:
3032 RETVAL
a0d0e21e
LW
3033
3034SysRet
3035tcdrain(fd)
3036 int fd
9163475a
NC
3037 ALIAS:
3038 close = 1
3039 dup = 2
3040 CODE:
3041 RETVAL = ix == 1 ? close(fd)
3042 : (ix < 1 ? tcdrain(fd) : dup(fd));
3043 OUTPUT:
3044 RETVAL
a0d0e21e
LW
3045
3046
3047SysRet
3048tcflow(fd, action)
3049 int fd
3050 int action
7a004119
NC
3051 ALIAS:
3052 tcflush = 1
3053 tcsendbreak = 2
3054 CODE:
3055 RETVAL = ix == 1 ? tcflush(fd, action)
3056 : (ix < 1 ? tcflow(fd, action) : tcsendbreak(fd, action));
3057 OUTPUT:
3058 RETVAL
a0d0e21e 3059
250d97fd 3060void
c1646883 3061asctime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = -1)
a0d0e21e
LW
3062 int sec
3063 int min
3064 int hour
3065 int mday
3066 int mon
3067 int year
3068 int wday
3069 int yday
3070 int isdst
250d97fd
NC
3071 ALIAS:
3072 mktime = 1
3073 PPCODE:
a0d0e21e 3074 {
250d97fd 3075 dXSTARG;
a0d0e21e 3076 struct tm mytm;
a748fe11 3077 init_tm(&mytm); /* XXX workaround - see init_tm() in core util.c */
a0d0e21e
LW
3078 mytm.tm_sec = sec;
3079 mytm.tm_min = min;
3080 mytm.tm_hour = hour;
3081 mytm.tm_mday = mday;
3082 mytm.tm_mon = mon;
3083 mytm.tm_year = year;
3084 mytm.tm_wday = wday;
3085 mytm.tm_yday = yday;
3086 mytm.tm_isdst = isdst;
250d97fd 3087 if (ix) {
e2054bce
TC
3088 const time_t result = mktime(&mytm);
3089 if (result == (time_t)-1)
250d97fd
NC
3090 SvOK_off(TARG);
3091 else if (result == 0)
3092 sv_setpvn(TARG, "0 but true", 10);
3093 else
3094 sv_setiv(TARG, (IV)result);
3095 } else {
3096 sv_setpv(TARG, asctime(&mytm));
3097 }
3098 ST(0) = TARG;
3099 XSRETURN(1);
a0d0e21e 3100 }
a0d0e21e
LW
3101
3102long
3103clock()
3104
3105char *
3106ctime(time)
748a9306 3107 Time_t &time
8990e307 3108
37120919
AD
3109void
3110times()
3111 PPCODE:
3112 struct tms tms;
3113 clock_t realtime;
3114 realtime = times( &tms );
924508f0 3115 EXTEND(SP,5);
9607fc9c 3116 PUSHs( sv_2mortal( newSViv( (IV) realtime ) ) );
3117 PUSHs( sv_2mortal( newSViv( (IV) tms.tms_utime ) ) );
3118 PUSHs( sv_2mortal( newSViv( (IV) tms.tms_stime ) ) );
3119 PUSHs( sv_2mortal( newSViv( (IV) tms.tms_cutime ) ) );
3120 PUSHs( sv_2mortal( newSViv( (IV) tms.tms_cstime ) ) );
37120919 3121
a0d0e21e
LW
3122double
3123difftime(time1, time2)
3124 Time_t time1
3125 Time_t time2
3126
8063af02
DM
3127#XXX: if $xsubpp::WantOptimize is always the default
3128# sv_setpv(TARG, ...) could be used rather than
3129# ST(0) = sv_2mortal(newSVpv(...))
3130void
e44f695e 3131strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)
dc57de01 3132 SV * fmt
a0d0e21e
LW
3133 int sec
3134 int min
3135 int hour
3136 int mday
3137 int mon
3138 int year
3139 int wday
3140 int yday
3141 int isdst
3142 CODE:
3143 {
5d37acd6 3144 char *buf;
f406a445 3145 SV *sv;
5d37acd6
DM
3146
3147 /* allowing user-supplied (rather than literal) formats
3148 * is normally frowned upon as a potential security risk;
3149 * but this is part of the API so we have to allow it */
3150 GCC_DIAG_IGNORE(-Wformat-nonliteral);
3151 buf = my_strftime(SvPV_nolen(fmt), sec, min, hour, mday, mon, year, wday, yday, isdst);
3152 GCC_DIAG_RESTORE;
f406a445 3153 sv = sv_newmortal();
2a74cb2d 3154 if (buf) {
9717af6d
KW
3155 STRLEN len = strlen(buf);
3156 sv_usepvn_flags(sv, buf, len, SV_HAS_TRAILING_NUL);
3157 if (SvUTF8(fmt)
3158 || (! is_ascii_string((U8*) buf, len)
3159 && is_utf8_string((U8*) buf, len)
323fd7cc 3160#ifdef USE_LOCALE_TIME
130c5df3
KW
3161 && _is_cur_LC_category_utf8(LC_TIME)
3162#endif
3163 )) {
8dbe7cf7
NC
3164 SvUTF8_on(sv);
3165 }
f406a445
KW
3166 }
3167 else { /* We can't distinguish between errors and just an empty
3168 * return; in all cases just return an empty string */
3169 SvUPGRADE(sv, SVt_PV);
3170 SvPV_set(sv, (char *) "");
3171 SvPOK_on(sv);
3172 SvCUR_set(sv, 0);
3173 SvLEN_set(sv, 0); /* Won't attempt to free the string when sv
3174 gets destroyed */
3175 }
3176 ST(0) = sv;
a0d0e21e
LW
3177 }
3178
3179void
3180tzset()
81ab4c44
SH
3181 PPCODE:
3182 my_tzset(aTHX);
a0d0e21e
LW
3183
3184void
3185tzname()
3186 PPCODE:
924508f0 3187 EXTEND(SP,2);
d3d34884
NC
3188 PUSHs(newSVpvn_flags(tzname[0], strlen(tzname[0]), SVs_TEMP));
3189 PUSHs(newSVpvn_flags(tzname[1], strlen(tzname[1]), SVs_TEMP));
a0d0e21e 3190
a0d0e21e
LW
3191char *
3192ctermid(s = 0)
3ab23a19
RGS
3193 char * s = 0;
3194 CODE:
3195#ifdef HAS_CTERMID_R
e02b9112 3196 s = (char *) safemalloc((size_t) L_ctermid);
3ab23a19
RGS
3197#endif
3198 RETVAL = ctermid(s);
3199 OUTPUT:
3200 RETVAL
d1fd7089 3201 CLEANUP:
3ab23a19 3202#ifdef HAS_CTERMID_R
d1fd7089 3203 Safefree(s);
3ab23a19 3204#endif
a0d0e21e
LW
3205
3206char *
3207cuserid(s = 0)
3208 char * s = 0;
56f4542c
TJ
3209 CODE:
3210#ifdef HAS_CUSERID
3211 RETVAL = cuserid(s);
3212#else
3213 RETVAL = 0;
3214 not_here("cuserid");
3215#endif
3216 OUTPUT:
3217 RETVAL
a0d0e21e
LW
3218
3219SysRetLong
3220fpathconf(fd, name)
3221 int fd
3222 int name
3223
3224SysRetLong
3225pathconf(filename, name)
3226 char * filename
3227 int name
3228
3229SysRet
3230pause()
20120e59
LT
3231 CLEANUP:
3232 PERL_ASYNC_CHECK();
a0d0e21e 3233
a387c53a
NC
3234unsigned int
3235sleep(seconds)
3236 unsigned int seconds
3237 CODE:
3238 RETVAL = PerlProc_sleep(seconds);
3239 OUTPUT:
3240 RETVAL
3241
a043a685
GW
3242SysRet
3243setgid(gid)
3244 Gid_t gid
3245
3246SysRet
3247setuid(uid)
3248 Uid_t uid
3249
a0d0e21e
LW
3250SysRetLong
3251sysconf(name)
3252 int name
3253
3254char *
3255ttyname(fd)
3256 int fd
a043a685 3257
c6c619a9 3258void
b5846a0b 3259getcwd()
8f95b30d
JH
3260 PPCODE:
3261 {
3262 dXSTARG;
89423764 3263 getcwd_sv(TARG);
8f95b30d
JH
3264 XSprePUSH; PUSHTARG;
3265 }
3266
0d7021f5
RGS
3267SysRet
3268lchown(uid, gid, path)
3269 Uid_t uid
3270 Gid_t gid
3271 char * path
3272 CODE:
3273#ifdef HAS_LCHOWN
3274 /* yes, the order of arguments is different,
3275 * but consistent with CORE::chown() */
3276 RETVAL = lchown(path, uid, gid);
3277#else
3278 RETVAL = not_here("lchown");
3279#endif
3280 OUTPUT:
3281 RETVAL