4 #define PERL_NO_GET_CONTEXT
13 /* XXX struct tm on some systems (SunOS4/BSD) contains extra (non POSIX)
14 * fields for which we don't have Configure support prior to Perl 5.8.0:
15 * char *tm_zone; -- abbreviation of timezone name
16 * long tm_gmtoff; -- offset from GMT in seconds
17 * To workaround core dumps from the uninitialised tm_zone we get the
18 * system to give us a reasonable struct to copy. This fix means that
19 * strftime uses the tm_zone and tm_gmtoff values returned by
20 * localtime(time()). That should give the desired result most of the
21 * time. But probably not always!
23 * This is a vestigial workaround for Perls prior to 5.8.0. We now
24 * rely on the initialization (still likely a workaround) in util.c.
26 #if !defined(PERL_VERSION) || PERL_VERSION < 8
28 #if defined(HAS_GNULIBC)
29 # ifndef STRUCT_TM_HASZONE
30 # define STRUCT_TM_HASZONE
32 # define USE_TM_GMTOFF
36 #endif /* end of pre-5.8 */
38 #define DAYS_PER_YEAR 365
39 #define DAYS_PER_QYEAR (4*DAYS_PER_YEAR+1)
40 #define DAYS_PER_CENT (25*DAYS_PER_QYEAR-1)
41 #define DAYS_PER_QCENT (4*DAYS_PER_CENT+1)
42 #define SECS_PER_HOUR (60*60)
43 #define SECS_PER_DAY (24*SECS_PER_HOUR)
44 /* parentheses deliberately absent on these two, otherwise they don't work */
45 #define MONTH_TO_DAYS 153/5
46 #define DAYS_TO_MONTH 5/153
47 /* offset to bias by March (month 4) 1st between month/mday & year finding */
48 #define YEAR_ADJUST (4*MONTH_TO_DAYS+1)
49 /* as used here, the algorithm leaves Sunday as day 1 unless we adjust it */
50 #define WEEKDAY_BIAS 6 /* (1+6)%7 makes Sunday 0 again */
52 #if !defined(PERL_VERSION) || PERL_VERSION < 8
54 #ifdef STRUCT_TM_HASZONE
56 my_init_tm(struct tm *ptm) /* see mktime, strftime and asctime */
60 Copy(localtime(&now), ptm, 1, struct tm);
64 # define my_init_tm(ptm)
68 /* use core version from util.c in 5.8.0 and later */
69 # define my_init_tm init_tm
75 * (1) The CRT maintains its own copy of the environment, separate from
78 * (2) CRT getenv() retrieves from this copy. CRT putenv() updates this
79 * copy, and then calls SetEnvironmentVariableA() to update the Win32API
82 * (3) win32_getenv() and win32_putenv() call GetEnvironmentVariableA() and
83 * SetEnvironmentVariableA() directly, bypassing the CRT copy of the
86 * (4) The CRT strftime() "%Z" implementation calls __tzset(). That
87 * calls CRT tzset(), but only the first time it is called, and in turn
88 * that uses CRT getenv("TZ") to retrieve the timezone info from the CRT
89 * local copy of the environment and hence gets the original setting as
90 * perl never updates the CRT copy when assigning to $ENV{TZ}.
92 * Therefore, we need to retrieve the value of $ENV{TZ} and call CRT
93 * putenv() to update the CRT copy of the environment (if it is different)
94 * whenever we're about to call tzset().
96 * In addition to all that, when perl is built with PERL_IMPLICIT_SYS
99 * (a) Each interpreter has its own copy of the environment inside the
100 * perlhost structure. That allows applications that host multiple
101 * independent Perl interpreters to isolate environment changes from
102 * each other. (This is similar to how the perlhost mechanism keeps a
103 * separate working directory for each Perl interpreter, so that calling
104 * chdir() will not affect other interpreters.)
106 * (b) Only the first Perl interpreter instantiated within a process will
107 * "write through" environment changes to the process environment.
109 * (c) Even the primary Perl interpreter won't update the CRT copy of the
110 * the environment, only the Win32API copy (it calls win32_putenv()).
112 * As with CPerlHost::Getenv() and CPerlHost::Putenv() themselves, it makes
113 * sense to only update the process environment when inside the main
114 * interpreter, but we don't have access to CPerlHost's m_bTopLevel member
115 * from here so we'll just have to check PL_curinterp instead.
117 * Therefore, we can simply #undef getenv() and putenv() so that those names
118 * always refer to the CRT functions, and explicitly call win32_getenv() to
119 * access perl's %ENV.
121 * We also #undef malloc() and free() to be sure we are using the CRT
122 * functions otherwise under PERL_IMPLICIT_SYS they are redefined to calls
123 * into VMem::Malloc() and VMem::Free() and all allocations will be freed
124 * when the Perl interpreter is being destroyed so we'd end up with a pointer
125 * into deallocated memory in environ[] if a program embedding a Perl
126 * interpreter continues to operate even after the main Perl interpreter has
129 * Note that we don't free() the malloc()ed memory unless and until we call
130 * malloc() again ourselves because the CRT putenv() function simply puts its
131 * pointer argument into the environ[] arrary (it doesn't make a copy of it)
132 * so this memory must otherwise be leaked.
138 # define getenv xcegetenv
139 # define putenv xceputenv
145 fix_win32_tzenv(void)
147 static char* oldenv = NULL;
149 const char* perl_tz_env = win32_getenv("TZ");
150 const char* crt_tz_env = getenv("TZ");
151 if (perl_tz_env == NULL)
153 if (crt_tz_env == NULL)
155 if (strcmp(perl_tz_env, crt_tz_env) != 0) {
156 STRLEN perl_tz_env_len = strlen(perl_tz_env);
157 newenv = (char*)malloc((perl_tz_env_len + 4) * sizeof(char));
158 if (newenv != NULL) {
159 /* putenv with old MS CRTs will cause a double free internally if you delete
160 an env var with the CRT env that doesn't exist in Win32 env (perl %ENV only
161 modifies the Win32 env, not CRT env), so always create the env var in Win32
162 env before deleting it with CRT env api, so the error branch never executes
163 in __crtsetenv after SetEnvironmentVariableA executes inside __crtsetenv.
165 VC 9/2008 and up dont have this bug, older VC (msvcrt80.dll and older) and
166 mingw (msvcrt.dll) have it see [perl #125529]
168 #if !(_MSC_VER >= 1500)
170 SetEnvironmentVariableA("TZ", "");
172 sprintf(newenv, "TZ=%s", perl_tz_env);
184 * my_tzset - wrapper to tzset() with a fix to make it work (better) on Win32.
185 * This code is duplicated in the POSIX module, so any changes made here
186 * should be made there too.
192 #if defined(USE_ITHREADS) && defined(PERL_IMPLICIT_SYS)
193 if (PL_curinterp == aTHX)
201 * my_mini_mktime - normalise struct tm values without the localtime()
202 * semantics (and overhead) of mktime(). Stolen shamelessly from Perl's
203 * Perl_mini_mktime() in util.c - for details on the algorithm, see that
207 my_mini_mktime(struct tm *ptm)
211 int month, mday, year, jday;
212 int odd_cent, odd_year;
214 year = 1900 + ptm->tm_year;
217 /* allow given yday with no month & mday to dominate the result */
218 if (ptm->tm_yday >= 0 && mday <= 0 && month <= 0) {
221 jday = 1 + ptm->tm_yday;
231 yearday = DAYS_PER_YEAR * year + year/4 - year/100 + year/400;
232 yearday += month*MONTH_TO_DAYS + mday + jday;
234 * Note that we don't know when leap-seconds were or will be,
235 * so we have to trust the user if we get something which looks
236 * like a sensible leap-second. Wild values for seconds will
237 * be rationalised, however.
239 if ((unsigned) ptm->tm_sec <= 60) {
246 secs += 60 * ptm->tm_min;
247 secs += SECS_PER_HOUR * ptm->tm_hour;
249 if (secs-(secs/SECS_PER_DAY*SECS_PER_DAY) < 0) {
250 /* got negative remainder, but need positive time */
251 /* back off an extra day to compensate */
252 yearday += (secs/SECS_PER_DAY)-1;
253 secs -= SECS_PER_DAY * (secs/SECS_PER_DAY - 1);
256 yearday += (secs/SECS_PER_DAY);
257 secs -= SECS_PER_DAY * (secs/SECS_PER_DAY);
260 else if (secs >= SECS_PER_DAY) {
261 yearday += (secs/SECS_PER_DAY);
262 secs %= SECS_PER_DAY;
264 ptm->tm_hour = secs/SECS_PER_HOUR;
265 secs %= SECS_PER_HOUR;
266 ptm->tm_min = secs/60;
269 /* done with time of day effects */
271 * The algorithm for yearday has (so far) left it high by 428.
272 * To avoid mistaking a legitimate Feb 29 as Mar 1, we need to
273 * bias it by 123 while trying to figure out what year it
274 * really represents. Even with this tweak, the reverse
275 * translation fails for years before A.D. 0001.
276 * It would still fail for Feb 29, but we catch that one below.
278 jday = yearday; /* save for later fixup vis-a-vis Jan 1 */
279 yearday -= YEAR_ADJUST;
280 year = (yearday / DAYS_PER_QCENT) * 400;
281 yearday %= DAYS_PER_QCENT;
282 odd_cent = yearday / DAYS_PER_CENT;
283 year += odd_cent * 100;
284 yearday %= DAYS_PER_CENT;
285 year += (yearday / DAYS_PER_QYEAR) * 4;
286 yearday %= DAYS_PER_QYEAR;
287 odd_year = yearday / DAYS_PER_YEAR;
289 yearday %= DAYS_PER_YEAR;
290 if (!yearday && (odd_cent==4 || odd_year==4)) { /* catch Feb 29 */
295 yearday += YEAR_ADJUST; /* recover March 1st crock */
296 month = yearday*DAYS_TO_MONTH;
297 yearday -= month*MONTH_TO_DAYS;
298 /* recover other leap-year adjustment */
307 ptm->tm_year = year - 1900;
309 ptm->tm_mday = yearday;
314 ptm->tm_mon = month - 1;
316 /* re-build yearday based on Jan 1 to get tm_yday */
318 yearday = year*DAYS_PER_YEAR + year/4 - year/100 + year/400;
319 yearday += 14*MONTH_TO_DAYS + 1;
320 ptm->tm_yday = jday - yearday;
321 /* fix tm_wday if not overridden by caller */
322 ptm->tm_wday = (jday + WEEKDAY_BIAS) % 7;
325 # if defined(WIN32) || (defined(__QNX__) && defined(__WATCOMC__))
326 # define strncasecmp(x,y,n) strnicmp(x,y,n)
329 /* strptime.c 0.1 (Powerdog) 94/03/27 */
330 /* strptime copied from freebsd with the following copyright: */
332 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
334 * Redistribution and use in source and binary forms, with or without
335 * modification, are permitted provided that the following conditions
338 * 1. Redistributions of source code must retain the above copyright
339 * notice, this list of conditions and the following disclaimer.
341 * 2. Redistributions in binary form must reproduce the above copyright
342 * notice, this list of conditions and the following disclaimer
343 * in the documentation and/or other materials provided with the
346 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
347 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
348 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
349 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
350 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
351 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
352 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
353 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
354 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
355 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
356 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
358 * The views and conclusions contained in the software and documentation
359 * are those of the authors and should not be interpreted as representing
360 * official policies, either expressed or implied, of Powerdog Industries.
366 static char * _strptime(pTHX_ const char *, const char *, struct tm *,
369 #define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
372 const char * mon[12];
373 const char * month[12];
374 const char * wday[7];
375 const char * weekday[7];
381 const char * date_fmt;
382 const char * alt_month[12];
387 struct lc_time_T _time_localebuf;
388 int _time_using_locale;
390 const struct lc_time_T _C_time_locale = {
392 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
393 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
395 "January", "February", "March", "April", "May", "June",
396 "July", "August", "September", "October", "November", "December"
398 "Sun", "Mon", "Tue", "Wed",
401 "Sunday", "Monday", "Tuesday", "Wednesday",
402 "Thursday", "Friday", "Saturday"
410 ** Since the C language standard calls for
411 ** "date, using locale's date format," anything goes.
412 ** Using just numbers (as here) makes Quakers happier;
413 ** it's also compatible with SVR4.
418 ** c_fmt (ctime-compatible)
419 ** Not used, just compatibility placeholder.
433 "January", "February", "March", "April", "May", "June",
434 "July", "August", "September", "October", "November", "December"
438 ** To determine short months / day order
443 ** To determine long months / day order
448 #define Locale (&_C_time_locale)
451 _strptime(pTHX_ const char *buf, const char *fmt, struct tm *tm, int *got_GMT)
457 int Ealternative, Oalternative;
459 /* There seems to be a slightly improved version at
460 * http://www.opensource.apple.com/source/Libc/Libc-583/stdtime/strptime-fbsd.c
461 * which we may end up borrowing more from
471 if (isspace((unsigned char)c))
472 while (*buf != 0 && isspace((unsigned char)*buf))
474 else if (c != *buf++)
491 buf = _strptime(aTHX_ buf, Locale->date_fmt, tm, got_GMT);
497 if (!isdigit((unsigned char)*buf))
500 /* XXX This will break for 3-digit centuries. */
502 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
510 tm->tm_year = i * 100 - 1900;
514 /* NOTE: c_fmt is intentionally ignored */
515 buf = _strptime(aTHX_ buf, "%a %Ef %T %Y", tm, got_GMT);
521 buf = _strptime(aTHX_ buf, "%m/%d/%y", tm, got_GMT);
527 if (Ealternative || Oalternative)
533 if (Ealternative || Oalternative)
542 buf = _strptime(aTHX_ buf, (c == 'f') ? Locale->Ef_fmt : Locale->EF_fmt, tm, got_GMT);
548 buf = _strptime(aTHX_ buf, "%H:%M", tm, got_GMT);
554 buf = _strptime(aTHX_ buf, "%I:%M:%S %p", tm, got_GMT);
559 case 'n': /* whitespace */
561 if (!isspace((unsigned char)*buf))
563 while (isspace((unsigned char)*buf))
568 buf = _strptime(aTHX_ buf, "%H:%M:%S", tm, got_GMT);
574 buf = _strptime(aTHX_ buf, Locale->X_fmt, tm, got_GMT);
580 buf = _strptime(aTHX_ buf, Locale->x_fmt, tm, got_GMT);
586 if (!isdigit((unsigned char)*buf))
590 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
595 if (i < 1 || i > 366)
604 if (*buf == 0 || isspace((unsigned char)*buf))
607 if (!isdigit((unsigned char)*buf))
611 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
627 if (*buf != 0 && isspace((unsigned char)*buf))
628 while (*ptr != 0 && !isspace((unsigned char)*ptr))
637 * Of these, %l is the only specifier explicitly
638 * documented as not being zero-padded. However,
639 * there is no harm in allowing zero-padding.
641 * XXX The %l specifier may gobble one too many
642 * digits if used incorrectly.
644 if (!isdigit((unsigned char)*buf))
648 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
653 if (c == 'H' || c == 'k') {
661 if (*buf != 0 && isspace((unsigned char)*buf))
662 while (*ptr != 0 && !isspace((unsigned char)*ptr))
668 * XXX This is bogus if parsed before hour-related
671 len = strlen(Locale->am);
672 if (strncasecmp(buf, Locale->am, len) == 0) {
673 if (tm->tm_hour > 12)
675 if (tm->tm_hour == 12)
681 len = strlen(Locale->pm);
682 if (strncasecmp(buf, Locale->pm, len) == 0) {
683 if (tm->tm_hour > 12)
685 if (tm->tm_hour != 12)
695 for (i = 0; i < (int)asizeof(Locale->weekday); i++) {
697 len = strlen(Locale->weekday[i]);
703 len = strlen(Locale->wday[i]);
710 if (i == (int)asizeof(Locale->weekday))
720 * XXX This is bogus, as we can not assume any valid
721 * information present in the tm structure at this
722 * point to calculate a real value, so just check the
725 if (!isdigit((unsigned char)*buf))
729 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
737 if (*buf != 0 && isspace((unsigned char)*buf))
738 while (*ptr != 0 && !isspace((unsigned char)*ptr))
743 if (!isdigit((unsigned char)*buf))
752 if (*buf != 0 && isspace((unsigned char)*buf))
753 while (*ptr != 0 && !isspace((unsigned char)*ptr))
760 * The %e specifier is explicitly documented as not
761 * being zero-padded but there is no harm in allowing
764 * XXX The %e specifier may gobble one too many
765 * digits if used incorrectly.
767 if (!isdigit((unsigned char)*buf))
771 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
781 if (*buf != 0 && isspace((unsigned char)*buf))
782 while (*ptr != 0 && !isspace((unsigned char)*ptr))
789 for (i = 0; i < (int)asizeof(Locale->month); i++) {
792 len = strlen(Locale->alt_month[i]);
794 Locale->alt_month[i],
800 len = strlen(Locale->month[i]);
806 len = strlen(Locale->mon[i]);
814 if (i == (int)asizeof(Locale->month))
822 if (!isdigit((unsigned char)*buf))
826 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
836 if (*buf != 0 && isspace((unsigned char)*buf))
837 while (*ptr != 0 && !isspace((unsigned char)*ptr))
851 n = strtol(buf, &cp, 10);
852 if (errno == ERANGE || (long)(t = n) != n) {
858 memset(&mytm, 0, sizeof(mytm));
859 my_init_tm(&mytm); /* XXX workaround - see my_init_tm() above */
861 tm->tm_sec = mytm.tm_sec;
862 tm->tm_min = mytm.tm_min;
863 tm->tm_hour = mytm.tm_hour;
864 tm->tm_mday = mytm.tm_mday;
865 tm->tm_mon = mytm.tm_mon;
866 tm->tm_year = mytm.tm_year;
867 tm->tm_wday = mytm.tm_wday;
868 tm->tm_yday = mytm.tm_yday;
869 tm->tm_isdst = mytm.tm_isdst;
875 if (*buf == 0 || isspace((unsigned char)*buf))
878 if (!isdigit((unsigned char)*buf))
881 len = (c == 'Y') ? 4 : 2;
882 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
889 if (c == 'y' && i < 69)
896 if (*buf != 0 && isspace((unsigned char)*buf))
897 while (*ptr != 0 && !isspace((unsigned char)*ptr))
906 for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp)
909 zonestr = (char *)malloc(cp - buf + 1);
914 strncpy(zonestr, buf, cp - buf);
915 zonestr[cp - buf] = '\0';
917 if (0 == strcmp(zonestr, "GMT")) {
921 if (!*got_GMT) return 0;
940 for (len = 4; len > 0; len--) {
941 if (isdigit((int)*buf)) {
949 tm->tm_hour -= sign * (i / 100);
950 tm->tm_min -= sign * (i % 100);
959 /* Saves alot of machine code.
960 Takes a (auto) SP, which may or may not have been PUSHed before, puts
961 tm struct members on Perl stack, then returns new, advanced, SP to caller.
962 Assign the return of push_common_tm to your SP, so you can continue to PUSH
963 or do a PUTBACK and return eventually.
964 !!!! push_common_tm does not touch PL_stack_sp !!!!
965 !!!! do not use PUTBACK then SPAGAIN semantics around push_common_tm !!!!
966 !!!! You must mortalize whatever push_common_tm put on stack yourself to
970 push_common_tm(pTHX_ SV ** SP, struct tm *mytm)
972 PUSHs(newSViv(mytm->tm_sec));
973 PUSHs(newSViv(mytm->tm_min));
974 PUSHs(newSViv(mytm->tm_hour));
975 PUSHs(newSViv(mytm->tm_mday));
976 PUSHs(newSViv(mytm->tm_mon));
977 PUSHs(newSViv(mytm->tm_year));
978 PUSHs(newSViv(mytm->tm_wday));
979 PUSHs(newSViv(mytm->tm_yday));
980 PUSHs(newSViv(mytm->tm_isdst));
984 /* specialized common end of 2 XSUBs
985 SV ** SP -- pass your (auto) SP, which has not been PUSHed before, but was
986 reset to 0 (PPCODE only or SP -= items or XSprePUSH)
987 tm *mytm -- a tm *, will be proprocessed with my_mini_mktime
988 return -- none, after calling return_11part_tm, you must call "return;"
992 return_11part_tm(pTHX_ SV ** SP, struct tm *mytm)
994 my_mini_mktime(mytm);
996 /* warn("tm: %d-%d-%d %d:%d:%d\n", mytm.tm_year, mytm.tm_mon, mytm.tm_mday, mytm.tm_hour, mytm.tm_min, mytm.tm_sec); */
998 SP = push_common_tm(aTHX_ SP, mytm);
1005 SV ** endsp = SP; /* the SV * under SP needs to be mortaled */
1006 SP -= (11 - 1); /* subtract 0 based count of SVs to mortal */
1007 /* mortal target of SP, then increment before function call
1008 so SP is already calculated before next comparison to not stall CPU */
1011 } while(SP <= endsp);
1016 MODULE = Time::Piece PACKAGE = Time::Piece
1021 _strftime(fmt, epoch, islocal = 1)
1032 mytm = *localtime(&epoch);
1034 mytm = *gmtime(&epoch);
1036 len = strftime(tmpbuf, sizeof tmpbuf, fmt, &mytm);
1038 ** The following is needed to handle to the situation where
1039 ** tmpbuf overflows. Basically we want to allocate a buffer
1040 ** and try repeatedly. The reason why it is so complicated
1041 ** is that getting a return value of 0 from strftime can indicate
1042 ** one of the following:
1043 ** 1. buffer overflowed,
1044 ** 2. illegal conversion specifier, or
1045 ** 3. the format string specifies nothing to be returned(not
1046 ** an error). This could be because format is an empty string
1047 ** or it specifies %p that yields an empty string in some locale.
1048 ** If there is a better way to make it portable, go ahead by
1051 if ((len > 0 && len < sizeof(tmpbuf)) || (len == 0 && *fmt == '\0'))
1052 ST(0) = sv_2mortal(newSVpv(tmpbuf, len));
1054 /* Possibly buf overflowed - try again with a bigger buf */
1055 int fmtlen = strlen(fmt);
1056 int bufsize = fmtlen + sizeof(tmpbuf);
1060 New(0, buf, bufsize, char);
1062 buflen = strftime(buf, bufsize, fmt, &mytm);
1063 if (buflen > 0 && buflen < bufsize)
1065 /* heuristic to prevent out-of-memory errors */
1066 if (bufsize > 100*fmtlen) {
1072 Renew(buf, bufsize, char);
1075 ST(0) = sv_2mortal(newSVpv(buf, buflen));
1079 ST(0) = sv_2mortal(newSVpv(tmpbuf, len));
1086 PUTBACK; /* makes rest of this function tailcall friendly */
1088 return; /* skip XSUBPP's PUTBACK */
1091 _strptime ( string, format )
1102 mytm.tm_isdst = -1; /* -1 means we don't know */
1105 remainder = (char *)_strptime(aTHX_ string, format, &mytm, &got_GMT);
1106 if (remainder == NULL) {
1107 croak("Error parsing time");
1109 if (*remainder != '\0') {
1110 warn("garbage at end of string in strptime: %s", remainder);
1113 return_11part_tm(aTHX_ SP, &mytm);
1117 _mini_mktime(int sec, int min, int hour, int mday, int mon, int year)
1127 mytm.tm_hour = hour;
1128 mytm.tm_mday = mday;
1130 mytm.tm_year = year;
1132 return_11part_tm(aTHX_ SP, &mytm);
1136 _crt_localtime(time_t sec)
1142 if(ix) mytm = *gmtime(&sec);
1143 else mytm = *localtime(&sec);
1144 /* Need to get: $s,$n,$h,$d,$m,$y */
1147 SP = push_common_tm(aTHX_ SP, &mytm);
1148 PUSHs(newSViv(mytm.tm_isdst));
1151 SV ** endsp = SP; /* the SV * under SP needs to be mortaled */
1152 SP -= (9 - 1); /* subtract 0 based count of SVs to mortal */
1153 /* mortal target of SP, then increment before function call
1154 so SP is already calculated before next comparison to not stall CPU */
1157 } while(SP <= endsp);