X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/ad64d0ecd555e97c5a216efca1ec5a96b7fd0b34..70b6a84e977a6211834eeab18dfebf4d45bd1688:/pp_sys.c diff --git a/pp_sys.c b/pp_sys.c index 8e1c8cd..08c1f83 100644 --- a/pp_sys.c +++ b/pp_sys.c @@ -13,6 +13,8 @@ * cloven by a great fissure, out of which the red glare came, now leaping * up, now dying down into darkness; and all the while far below there was * a rumour and a trouble as of great engines throbbing and labouring. + * + * [p.945 of _The Lord of the Rings_, VI/iii: "Mount Doom"] */ /* This file contains system pp ("push/pop") functions that @@ -27,6 +29,10 @@ #include "EXTERN.h" #define PERL_IN_PP_SYS_C #include "perl.h" +#ifndef PERL_MICRO +# include "time64.h" +# include "time64.c" +#endif #ifdef I_SHADOW /* Shadow password support for solaris - pdo@cs.umd.edu @@ -199,15 +205,6 @@ void endservent(void); #undef PERL_EFF_ACCESS /* EFFective uid/gid ACCESS */ -/* AIX 5.2 and below use mktime for localtime, and defines the edge case - * for time 0x7fffffff to be valid only in UTC. AIX 5.3 provides localtime64 - * available in the 32bit environment, which could warrant Configure - * checks in the future. - */ -#ifdef _AIX -#define LOCALTIME_EDGECASE_BROKEN -#endif - /* F_OK unused: if stat() cannot find it... */ #if !defined(PERL_EFF_ACCESS) && defined(HAS_ACCESS) && defined(EFF_ONLY_OK) && !defined(NO_EFF_ONLY_OK) @@ -385,7 +382,7 @@ PP(pp_glob) #endif /* !VMS */ SAVESPTR(PL_last_in_gv); /* We don't want this to be permanent. */ - PL_last_in_gv = (GV*)*PL_stack_sp--; + PL_last_in_gv = MUTABLE_GV(*PL_stack_sp--); SAVESPTR(PL_rs); /* This is not permanent, either. */ PL_rs = newSVpvs_flags("\000", SVs_TEMP); @@ -519,7 +516,7 @@ PP(pp_open) STRLEN len; bool ok; - GV * const gv = (GV *)*++MARK; + GV * const gv = MUTABLE_GV(*++MARK); if (!isGV(gv)) DIE(aTHX_ PL_no_usym, "filehandle"); @@ -569,7 +566,7 @@ PP(pp_open) PP(pp_close) { dVAR; dSP; - GV * const gv = (MAXARG == 0) ? PL_defoutgv : (GV*)POPs; + GV * const gv = (MAXARG == 0) ? PL_defoutgv : MUTABLE_GV(POPs); if (gv) { IO * const io = GvIO(gv); @@ -601,8 +598,8 @@ PP(pp_pipe_op) register IO *wstio; int fd[2]; - GV * const wgv = (GV*)POPs; - GV * const rgv = (GV*)POPs; + GV * const wgv = MUTABLE_GV(POPs); + GV * const rgv = MUTABLE_GV(POPs); if (!rgv || !wgv) goto badexit; @@ -661,7 +658,7 @@ PP(pp_fileno) if (MAXARG < 1) RETPUSHUNDEF; - gv = (GV*)POPs; + gv = MUTABLE_GV(POPs); if (gv && (io = GvIO(gv)) && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar))) @@ -734,7 +731,7 @@ PP(pp_binmode) discp = POPs; } - gv = (GV*)POPs; + gv = MUTABLE_GV(POPs); if (gv && (io = GvIO(gv))) { MAGIC * const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar); @@ -808,7 +805,7 @@ PP(pp_tie) case SVt_PVGV: if (isGV_with_GP(varsv)) { #ifdef GV_UNIQUE_CHECK - if (GvUNIQUE((GV*)varsv)) { + if (GvUNIQUE((const GV *)varsv)) { Perl_croak(aTHX_ "Attempt to tie unique GV"); } #endif @@ -1027,7 +1024,7 @@ PP(pp_sselect) if (SvIsCOW(sv)) sv_force_normal_flags(sv, 0); if (SvREADONLY(sv) && !(SvPOK(sv) && SvCUR(sv) == 0)) - DIE(aTHX_ PL_no_modify); + DIE(aTHX_ "%s", PL_no_modify); } if (!SvPOK(sv)) { if (ckWARN(WARN_MISC)) @@ -1154,6 +1151,17 @@ PP(pp_sselect) #endif } +/* +=for apidoc setdefout + +Sets PL_defoutgv, the default file handle for output, to the passed in +typeglob. As PL_defoutgv "owns" a reference on its typeglob, the reference +count of the passed in typeglob is increased by one, and the reference count +of the typeglob that PL_defoutgv points to is decreased by one. + +=cut +*/ + void Perl_setdefout(pTHX_ GV *gv) { @@ -1168,7 +1176,7 @@ PP(pp_select) { dVAR; dSP; dTARGET; HV *hv; - GV * const newdefout = (PL_op->op_private > 0) ? ((GV *) POPs) : NULL; + GV * const newdefout = (PL_op->op_private > 0) ? (MUTABLE_GV(POPs)) : NULL; GV * egv = GvEGV(PL_defoutgv); if (!egv) @@ -1200,7 +1208,7 @@ PP(pp_getc) { dVAR; dSP; dTARGET; IO *io = NULL; - GV * const gv = (MAXARG==0) ? PL_stdingv : (GV*)POPs; + GV * const gv = (MAXARG==0) ? PL_stdingv : MUTABLE_GV(POPs); if (gv && (io = GvIO(gv))) { MAGIC * const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar); @@ -1276,7 +1284,7 @@ PP(pp_enterwrite) if (MAXARG == 0) gv = PL_defoutgv; else { - gv = (GV*)POPs; + gv = MUTABLE_GV(POPs); if (!gv) gv = PL_defoutgv; } @@ -1447,7 +1455,8 @@ PP(pp_prtf) PerlIO *fp; SV *sv; - GV * const gv = (PL_op->op_flags & OPf_STACKED) ? (GV*)*++MARK : PL_defoutgv; + GV * const gv + = (PL_op->op_flags & OPf_STACKED) ? MUTABLE_GV(*++MARK) : PL_defoutgv; if (gv && (io = GvIO(gv))) { MAGIC * const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar); @@ -1519,7 +1528,7 @@ PP(pp_sysopen) const int perm = (MAXARG > 3) ? POPi : 0666; const int mode = POPi; SV * const sv = POPs; - GV * const gv = (GV *)POPs; + GV * const gv = MUTABLE_GV(POPs); STRLEN len; /* Need TIEHANDLE method ? */ @@ -1555,7 +1564,7 @@ PP(pp_sysread) STRLEN charskip = 0; STRLEN skip = 0; - GV * const gv = (GV*)*++MARK; + GV * const gv = MUTABLE_GV(*++MARK); if ((PL_op->op_type == OP_READ || PL_op->op_type == OP_SYSREAD) && gv && (io = GvIO(gv)) ) { @@ -1801,7 +1810,7 @@ PP(pp_send) bool doing_utf8; U8 *tmpbuf = NULL; - GV *const gv = (GV*)*++MARK; + GV *const gv = MUTABLE_GV(*++MARK); if (PL_op->op_type == OP_SYSWRITE && gv && (io = GvIO(gv))) { MAGIC * const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar); @@ -1809,9 +1818,8 @@ PP(pp_send) SV *sv; if (MARK == SP - 1) { - EXTEND(SP, 1000); - sv = sv_2mortal(newSViv(sv_len(*SP))); - PUSHs(sv); + sv = *SP; + mXPUSHi(sv_len(sv)); PUTBACK; } @@ -2011,51 +2019,60 @@ PP(pp_eof) { dVAR; dSP; GV *gv; + IO *io; + MAGIC *mg; - if (MAXARG == 0) { - if (PL_op->op_flags & OPf_SPECIAL) { /* eof() */ - IO *io; - gv = PL_last_in_gv = GvEGV(PL_argvgv); - io = GvIO(gv); - if (io && !IoIFP(io)) { - if ((IoFLAGS(io) & IOf_START) && av_len(GvAVn(gv)) < 0) { - IoLINES(io) = 0; - IoFLAGS(io) &= ~IOf_START; - do_open(gv, "-", 1, FALSE, O_RDONLY, 0, NULL); - if ( GvSV(gv) ) { - sv_setpvs(GvSV(gv), "-"); - } - else { - GvSV(gv) = newSVpvs("-"); - } - SvSETMAGIC(GvSV(gv)); - } - else if (!nextargv(gv)) - RETPUSHYES; - } - } + if (MAXARG) + gv = PL_last_in_gv = MUTABLE_GV(POPs); /* eof(FH) */ + else if (PL_op->op_flags & OPf_SPECIAL) + gv = PL_last_in_gv = GvEGV(PL_argvgv); /* eof() - ARGV magic */ + else + gv = PL_last_in_gv; /* eof */ + + if (!gv) + RETPUSHNO; + + if ((io = GvIO(gv)) && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar))) { + PUSHMARK(SP); + XPUSHs(SvTIED_obj(MUTABLE_SV(io), mg)); + /* + * in Perl 5.12 and later, the additional paramter is a bitmask: + * 0 = eof + * 1 = eof(FH) + * 2 = eof() <- ARGV magic + */ + if (MAXARG) + mPUSHi(1); /* 1 = eof(FH) - simple, explicit FH */ + else if (PL_op->op_flags & OPf_SPECIAL) + mPUSHi(2); /* 2 = eof() - ARGV magic */ else - gv = PL_last_in_gv; /* eof */ + mPUSHi(0); /* 0 = eof - simple, implicit FH */ + PUTBACK; + ENTER; + call_method("EOF", G_SCALAR); + LEAVE; + SPAGAIN; + RETURN; } - else - gv = PL_last_in_gv = (GV*)POPs; /* eof(FH) */ - if (gv) { - IO * const io = GvIO(gv); - MAGIC * mg; - if (io && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar))) { - PUSHMARK(SP); - XPUSHs(SvTIED_obj(MUTABLE_SV(io), mg)); - PUTBACK; - ENTER; - call_method("EOF", G_SCALAR); - LEAVE; - SPAGAIN; - RETURN; + if (!MAXARG && (PL_op->op_flags & OPf_SPECIAL)) { /* eof() */ + if (io && !IoIFP(io)) { + if ((IoFLAGS(io) & IOf_START) && av_len(GvAVn(gv)) < 0) { + IoLINES(io) = 0; + IoFLAGS(io) &= ~IOf_START; + do_open(gv, "-", 1, FALSE, O_RDONLY, 0, NULL); + if (GvSV(gv)) + sv_setpvs(GvSV(gv), "-"); + else + GvSV(gv) = newSVpvs("-"); + SvSETMAGIC(GvSV(gv)); + } + else if (!nextargv(gv)) + RETPUSHYES; } } - PUSHs(boolSV(!gv || do_eof(gv))); + PUSHs(boolSV(do_eof(gv))); RETURN; } @@ -2066,7 +2083,7 @@ PP(pp_tell) IO *io; if (MAXARG != 0) - PL_last_in_gv = (GV*)POPs; + PL_last_in_gv = MUTABLE_GV(POPs); gv = PL_last_in_gv; if (gv && (io = GvIO(gv))) { @@ -2101,7 +2118,7 @@ PP(pp_sysseek) const Off_t offset = (Off_t)SvIVx(POPs); #endif - GV * const gv = PL_last_in_gv = (GV*)POPs; + GV * const gv = PL_last_in_gv = MUTABLE_GV(POPs); IO *io; if (gv && (io = GvIO(gv))) { @@ -2199,11 +2216,11 @@ PP(pp_truncate) const char *name; if (isGV_with_GP(sv)) { - tmpgv = (GV*)sv; /* *main::FRED for example */ + tmpgv = MUTABLE_GV(sv); /* *main::FRED for example */ goto do_ftruncate_gv; } else if (SvROK(sv) && isGV_with_GP(SvRV(sv))) { - tmpgv = (GV*) SvRV(sv); /* \*main::FRED for example */ + tmpgv = MUTABLE_GV(SvRV(sv)); /* \*main::FRED for example */ goto do_ftruncate_gv; } else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVIO) { @@ -2245,7 +2262,7 @@ PP(pp_ioctl) SV * const argsv = POPs; const unsigned int func = POPu; const int optype = PL_op->op_type; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); IO * const io = gv ? GvIOn(gv) : NULL; char *s; IV retval; @@ -2322,7 +2339,7 @@ PP(pp_flock) IO *io = NULL; PerlIO *fp; const int argtype = POPi; - GV * const gv = (MAXARG == 0) ? PL_last_in_gv : (GV*)POPs; + GV * const gv = (MAXARG == 0) ? PL_last_in_gv : MUTABLE_GV(POPs); if (gv && (io = GvIO(gv))) fp = IoIFP(io); @@ -2357,7 +2374,7 @@ PP(pp_socket) const int protocol = POPi; const int type = POPi; const int domain = POPi; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = gv ? GvIOn(gv) : NULL; int fd; @@ -2407,8 +2424,8 @@ PP(pp_sockpair) const int protocol = POPi; const int type = POPi; const int domain = POPi; - GV * const gv2 = (GV*)POPs; - GV * const gv1 = (GV*)POPs; + GV * const gv2 = MUTABLE_GV(POPs); + GV * const gv1 = MUTABLE_GV(POPs); register IO * const io1 = gv1 ? GvIOn(gv1) : NULL; register IO * const io2 = gv2 ? GvIOn(gv2) : NULL; int fd[2]; @@ -2468,7 +2485,7 @@ PP(pp_bind) SV * const addrsv = POPs; /* OK, so on what platform does bind modify addr? */ const char *addr; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = GvIOn(gv); STRLEN len; @@ -2497,7 +2514,7 @@ PP(pp_connect) #ifdef HAS_SOCKET dVAR; dSP; SV * const addrsv = POPs; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = GvIOn(gv); const char *addr; STRLEN len; @@ -2527,7 +2544,7 @@ PP(pp_listen) #ifdef HAS_SOCKET dVAR; dSP; const int backlog = POPi; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = gv ? GvIOn(gv) : NULL; if (!gv || !io || !IoIFP(io)) @@ -2560,8 +2577,8 @@ PP(pp_accept) #else Sock_size_t len = sizeof namebuf; #endif - GV * const ggv = (GV*)POPs; - GV * const ngv = (GV*)POPs; + GV * const ggv = MUTABLE_GV(POPs); + GV * const ngv = MUTABLE_GV(POPs); int fd; if (!ngv) @@ -2632,7 +2649,7 @@ PP(pp_shutdown) #ifdef HAS_SOCKET dVAR; dSP; dTARGET; const int how = POPi; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = GvIOn(gv); if (!io || !IoIFP(io)) @@ -2659,7 +2676,7 @@ PP(pp_ssockopt) SV * const sv = (optype == OP_GSOCKOPT) ? sv_2mortal(newSV(257)) : POPs; const unsigned int optname = (unsigned int) POPi; const unsigned int lvl = (unsigned int) POPi; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = GvIOn(gv); int fd; Sock_size_t len; @@ -2733,7 +2750,7 @@ PP(pp_getpeername) #ifdef HAS_SOCKET dVAR; dSP; const int optype = PL_op->op_type; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = GvIOn(gv); Sock_size_t len; SV *sv; @@ -2846,10 +2863,10 @@ PP(pp_stat) else { SV* const sv = POPs; if (isGV_with_GP(sv)) { - gv = (GV*)sv; + gv = MUTABLE_GV(sv); goto do_fstat; } else if(SvROK(sv) && isGV_with_GP(SvRV(sv))) { - gv = (GV*)SvRV(sv); + gv = MUTABLE_GV(SvRV(sv)); if (PL_op->op_type == OP_LSTAT) goto do_fstat_warning_check; goto do_fstat; @@ -3204,9 +3221,9 @@ PP(pp_fttty) if (PL_op->op_flags & OPf_REF) gv = cGVOP_gv; else if (isGV(TOPs)) - gv = (GV*)POPs; + gv = MUTABLE_GV(POPs); else if (SvROK(TOPs) && isGV(SvRV(TOPs))) - gv = (GV*)SvRV(POPs); + gv = MUTABLE_GV(SvRV(POPs)); else gv = gv_fetchsv(tmpsv = POPs, 0, SVt_PVIO); @@ -3253,9 +3270,9 @@ PP(pp_fttext) if (PL_op->op_flags & OPf_REF) gv = cGVOP_gv; else if (isGV(TOPs)) - gv = (GV*)POPs; + gv = MUTABLE_GV(POPs); else if (SvROK(TOPs) && isGV(SvRV(TOPs))) - gv = (GV*)SvRV(POPs); + gv = MUTABLE_GV(SvRV(POPs)); else gv = NULL; @@ -3405,10 +3422,10 @@ PP(pp_chdir) gv = gv_fetchsv(sv, 0, SVt_PVIO); } else if (isGV_with_GP(sv)) { - gv = (GV*)sv; + gv = MUTABLE_GV(sv); } else if (SvROK(sv) && isGV_with_GP(SvRV(sv))) { - gv = (GV*)SvRV(sv); + gv = MUTABLE_GV(SvRV(sv)); } else { tmps = SvPV_nolen_const(sv); @@ -3761,7 +3778,7 @@ PP(pp_open_dir) #if defined(Direntry_t) && defined(HAS_READDIR) dVAR; dSP; const char * const dirname = POPpconstx; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = GvIOn(gv); if (!io) @@ -3798,7 +3815,7 @@ PP(pp_readdir) SV *sv; const I32 gimme = GIMME; - GV * const gv = (GV *)POPs; + GV * const gv = MUTABLE_GV(POPs); register const Direntry_t *dp; register IO * const io = GvIOn(gv); @@ -3852,7 +3869,7 @@ PP(pp_telldir) # if !defined(HAS_TELLDIR_PROTO) || defined(NEED_TELLDIR_PROTO) long telldir (DIR *); # endif - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = GvIOn(gv); if (!io || !IoDIRP(io)) { @@ -3879,7 +3896,7 @@ PP(pp_seekdir) #if defined(HAS_SEEKDIR) || defined(seekdir) dVAR; dSP; const long along = POPl; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = GvIOn(gv); if (!io || !IoDIRP(io)) { @@ -3905,7 +3922,7 @@ PP(pp_rewinddir) { #if defined(HAS_REWINDDIR) || defined(rewinddir) dVAR; dSP; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = GvIOn(gv); if (!io || !IoDIRP(io)) { @@ -3930,7 +3947,7 @@ PP(pp_closedir) { #if defined(Direntry_t) && defined(HAS_READDIR) dVAR; dSP; - GV * const gv = (GV*)POPs; + GV * const gv = MUTABLE_GV(POPs); register IO * const io = GvIOn(gv); if (!io || !IoDIRP(io)) { @@ -4300,6 +4317,7 @@ PP(pp_setpgrp) if (MAXARG < 2) { pgrp = 0; pid = 0; + XPUSHi(-1); } else { pgrp = POPi; @@ -4402,104 +4420,105 @@ PP(pp_tms) #endif /* HAS_TIMES */ } -#ifdef LOCALTIME_EDGECASE_BROKEN -static struct tm *S_my_localtime (pTHX_ Time_t *tp) -{ - auto time_t T; - auto struct tm *P; - - /* No workarounds in the valid range */ - if (!tp || *tp < 0x7fff573f || *tp >= 0x80000000) - return (localtime (tp)); - - /* This edge case is to workaround the undefined behaviour, where the - * TIMEZONE makes the time go beyond the defined range. - * gmtime (0x7fffffff) => 2038-01-19 03:14:07 - * If there is a negative offset in TZ, like MET-1METDST, some broken - * implementations of localtime () (like AIX 5.2) barf with bogus - * return values: - * 0x7fffffff gmtime 2038-01-19 03:14:07 - * 0x7fffffff localtime 1901-12-13 21:45:51 - * 0x7fffffff mylocaltime 2038-01-19 04:14:07 - * 0x3c19137f gmtime 2001-12-13 20:45:51 - * 0x3c19137f localtime 2001-12-13 21:45:51 - * 0x3c19137f mylocaltime 2001-12-13 21:45:51 - * Given that legal timezones are typically between GMT-12 and GMT+12 - * we turn back the clock 23 hours before calling the localtime - * function, and add those to the return value. This will never cause - * day wrapping problems, since the edge case is Tue Jan *19* - */ - T = *tp - 82800; /* 23 hour. allows up to GMT-23 */ - P = localtime (&T); - P->tm_hour += 23; - if (P->tm_hour >= 24) { - P->tm_hour -= 24; - P->tm_mday++; /* 18 -> 19 */ - P->tm_wday++; /* Mon -> Tue */ - P->tm_yday++; /* 18 -> 19 */ - } - return (P); -} /* S_my_localtime */ -#endif - PP(pp_gmtime) { dVAR; dSP; +#ifdef PERL_MICRO Time_t when; - const struct tm *tmbuf; + const struct tm *err; + struct tm tmbuf; +#else + Time64_T when; + struct TM tmbuf; + struct TM *err; +#endif + const char *opname = PL_op->op_type == OP_LOCALTIME ? "localtime" : "gmtime"; static const char * const dayname[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static const char * const monname[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; +#ifdef PERL_MICRO if (MAXARG < 1) (void)time(&when); else -#ifdef BIG_TIME - when = (Time_t)SvNVx(POPs); -#else when = (Time_t)SvIVx(POPs); -#endif if (PL_op->op_type == OP_LOCALTIME) -#ifdef LOCALTIME_EDGECASE_BROKEN - tmbuf = S_my_localtime(aTHX_ &when); + err = localtime(&when); + else + err = gmtime(&when); + + if (!err) + tmbuf = *err; #else - tmbuf = localtime(&when); -#endif + if (MAXARG < 1) { + time_t now; + (void)time(&now); + when = (Time64_T)now; + } + else { + /* XXX POPq uses an SvIV so it won't work with 32 bit integer scalars + using a double causes an unfortunate loss of accuracy on high numbers. + What we really need is an SvQV. + */ + double input = POPn; + when = (Time64_T)input; + if( when != input ) { + Perl_warner(aTHX_ packWARN(WARN_OVERFLOW), + "%s(%.0f) too large", opname, input); + } + } + + if (PL_op->op_type == OP_LOCALTIME) + err = localtime64_r(&when, &tmbuf); else - tmbuf = gmtime(&when); + err = gmtime64_r(&when, &tmbuf); +#endif - if (GIMME != G_ARRAY) { + if( err == NULL ) { + /* XXX %lld broken for quads */ + Perl_warner(aTHX_ packWARN(WARN_OVERFLOW), + "%s(%.0f) failed", opname, (double)when); + } + + if (GIMME != G_ARRAY) { /* scalar context */ SV *tsv; + /* XXX newSVpvf()'s %lld type is broken, so cheat with a double */ + double year = (double)tmbuf.tm_year + 1900; + EXTEND(SP, 1); EXTEND_MORTAL(1); - if (!tmbuf) + if (err == NULL) RETPUSHUNDEF; - tsv = Perl_newSVpvf(aTHX_ "%s %s %2d %02d:%02d:%02d %d", - dayname[tmbuf->tm_wday], - monname[tmbuf->tm_mon], - tmbuf->tm_mday, - tmbuf->tm_hour, - tmbuf->tm_min, - tmbuf->tm_sec, - tmbuf->tm_year + 1900); + + tsv = Perl_newSVpvf(aTHX_ "%s %s %2d %02d:%02d:%02d %.0f", + dayname[tmbuf.tm_wday], + monname[tmbuf.tm_mon], + tmbuf.tm_mday, + tmbuf.tm_hour, + tmbuf.tm_min, + tmbuf.tm_sec, + year); mPUSHs(tsv); } - else if (tmbuf) { + else { /* list context */ + if ( err == NULL ) + RETURN; + EXTEND(SP, 9); EXTEND_MORTAL(9); - mPUSHi(tmbuf->tm_sec); - mPUSHi(tmbuf->tm_min); - mPUSHi(tmbuf->tm_hour); - mPUSHi(tmbuf->tm_mday); - mPUSHi(tmbuf->tm_mon); - mPUSHi(tmbuf->tm_year); - mPUSHi(tmbuf->tm_wday); - mPUSHi(tmbuf->tm_yday); - mPUSHi(tmbuf->tm_isdst); + mPUSHi(tmbuf.tm_sec); + mPUSHi(tmbuf.tm_min); + mPUSHi(tmbuf.tm_hour); + mPUSHi(tmbuf.tm_mday); + mPUSHi(tmbuf.tm_mon); + mPUSHn(tmbuf.tm_year); + mPUSHi(tmbuf.tm_wday); + mPUSHi(tmbuf.tm_yday); + mPUSHi(tmbuf.tm_isdst); } RETURN; } @@ -5164,13 +5183,13 @@ PP(pp_gpwent) * has a different API than the Solaris/IRIX one. */ # if defined(HAS_GETSPNAM) && !defined(_AIX) { - const int saverrno = errno; + dSAVE_ERRNO; const struct spwd * const spwent = getspnam(pwent->pw_name); /* Save and restore errno so that * underprivileged attempts seem * to have never made the unsccessful * attempt to retrieve the shadow password. */ - errno = saverrno; + RESTORE_ERRNO; if (spwent && spwent->sp_pwdp) sv_setpv(sv, spwent->sp_pwdp); } @@ -5548,15 +5567,15 @@ static int lockf_emulate_flock(int fd, int operation) { int i; - const int save_errno = errno; Off_t pos; + dSAVE_ERRNO; /* flock locks entire file so for lockf we need to do the same */ pos = PerlLIO_lseek(fd, (Off_t)0, SEEK_CUR); /* get pos to restore later */ if (pos > 0) /* is seekable and needs to be repositioned */ if (PerlLIO_lseek(fd, (Off_t)0, SEEK_SET) < 0) pos = -1; /* seek failed, so don't seek back afterwards */ - errno = save_errno; + RESTORE_ERRNO; switch (operation) {