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