summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2001-04-19 00:54:54 +0000
committerJarkko Hietaniemi <jhi@iki.fi>2001-04-19 00:54:54 +0000
commitb3c85772f7a16b79e679c78c9638a7afa4856432 (patch)
treeb6a7e16b673c4518a86a2fd1e9f5a4da514b4d2b /util.c
parente72cf795050cdfe9905e00270c38ba2547626581 (diff)
downloadperl-b3c85772f7a16b79e679c78c9638a7afa4856432.tar.gz
Move the strftime() wrapper from POSIX.xs to util.c
as my_strftime(), requires HAS_STRFTIME. p4raw-id: //depot/perl@9746
Diffstat (limited to 'util.c')
-rw-r--r--util.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/util.c b/util.c
index 542d0ddc73..4ccd589ecd 100644
--- a/util.c
+++ b/util.c
@@ -4361,3 +4361,69 @@ mini_mktime(struct tm *ptm)
if ((unsigned)ptm->tm_wday > 6)
ptm->tm_wday = (jday + WEEKDAY_BIAS) % 7;
}
+
+char *
+my_strftime(char *fmt, int sec, int min, int hour, int mday, int mon, int year, int wday, int yday, int isdst)
+{
+#ifdef HAS_STRFTIME
+ char *buf;
+ int buflen;
+ struct tm mytm;
+ int len;
+
+ init_tm(&mytm); /* XXX workaround - see init_tm() above */
+ mytm.tm_sec = sec;
+ mytm.tm_min = min;
+ mytm.tm_hour = hour;
+ mytm.tm_mday = mday;
+ mytm.tm_mon = mon;
+ mytm.tm_year = year;
+ mytm.tm_wday = wday;
+ mytm.tm_yday = yday;
+ mytm.tm_isdst = isdst;
+ mini_mktime(&mytm);
+ buflen = 64;
+ New(0, buf, buflen, char);
+ len = strftime(buf, buflen, fmt, &mytm);
+ /*
+ ** The following is needed to handle to the situation where
+ ** tmpbuf overflows. Basically we want to allocate a buffer
+ ** and try repeatedly. The reason why it is so complicated
+ ** is that getting a return value of 0 from strftime can indicate
+ ** one of the following:
+ ** 1. buffer overflowed,
+ ** 2. illegal conversion specifier, or
+ ** 3. the format string specifies nothing to be returned(not
+ ** an error). This could be because format is an empty string
+ ** or it specifies %p that yields an empty string in some locale.
+ ** If there is a better way to make it portable, go ahead by
+ ** all means.
+ */
+ if ((len > 0 && len < buflen) || (len == 0 && *fmt == '\0'))
+ return buf;
+ else {
+ /* Possibly buf overflowed - try again with a bigger buf */
+ int fmtlen = strlen(fmt);
+ int bufsize = fmtlen + buflen;
+
+ New(0, buf, bufsize, char);
+ while (buf) {
+ buflen = strftime(buf, bufsize, fmt, &mytm);
+ if (buflen > 0 && buflen < bufsize)
+ break;
+ /* heuristic to prevent out-of-memory errors */
+ if (bufsize > 100*fmtlen) {
+ Safefree(buf);
+ buf = NULL;
+ break;
+ }
+ bufsize *= 2;
+ Renew(buf, bufsize, char);
+ }
+ return buf;
+ }
+#else
+ Perl_croak(aTHX_ "panic: no strftime");
+#endif
+}
+