Date: Tue, 21 May 2002 19:51:07 +0100 From: Tony Finch <dot@dotat.at> To: freebsd-audit@freebsd.org Subject: strptime %z support Message-ID: <20020521195107.A4260@chiark.greenend.org.uk>
next in thread | raw e-mail | index | archive | help
This is a work-in-progress patch against -STABLE. The reason I'm posting here is because I have a feeling I'm barking up the wrong tree -- I'm not sure how to get it to return a struct tm with the right timezone filled in so it currently falls back to GMT. It also replaces a pthreads lock with re-entrant code. Any comments would be welcome. Tony. -- f.a.n.finch <dot@dotat.at> http://dotat.at/ SOUTHEAST ICELAND: SOUTHEASTERLY 6 TO GALE 8, BACKING EAST OR NORTHEAST 4 OR 5. SHOWERS. MODERATE. Index: strptime.c =================================================================== RCS file: /home/ncvs/src/lib/libc/stdtime/strptime.c,v retrieving revision 1.17.2.3 diff -u -r1.17.2.3 strptime.c --- strptime.c 12 Mar 2002 17:24:54 -0000 1.17.2.3 +++ strptime.c 21 May 2002 18:39:23 -0000 @@ -75,18 +75,17 @@ #endif #include "timelocal.h" -static char * _strptime(const char *, const char *, struct tm *); +static char * _strptime(const char *, const char *, struct tm *, int *); -#ifdef _THREAD_SAFE -static struct pthread_mutex _gotgmt_mutexd = PTHREAD_MUTEX_STATIC_INITIALIZER; -static pthread_mutex_t gotgmt_mutex = &_gotgmt_mutexd; -#endif -static int got_GMT; +enum { + NORMALIZE_GMT = 1, + NORMALIZE_LOCAL = 2 +}; #define asizeof(a) (sizeof (a) / sizeof ((a)[0])) static char * -_strptime(const char *buf, const char *fmt, struct tm *tm) +_strptime(const char *buf, const char *fmt, struct tm *tm, int *flagp) { char c; const char *ptr; @@ -123,7 +122,7 @@ break; case '+': - buf = _strptime(buf, tptr->date_fmt, tm); + buf = _strptime(buf, tptr->date_fmt, tm, flagp); if (buf == 0) return 0; break; @@ -146,13 +145,13 @@ break; case 'c': - buf = _strptime(buf, tptr->c_fmt, tm); + buf = _strptime(buf, tptr->c_fmt, tm, flagp); if (buf == 0) return 0; break; case 'D': - buf = _strptime(buf, "%m/%d/%y", tm); + buf = _strptime(buf, "%m/%d/%y", tm, flagp); if (buf == 0) return 0; break; @@ -170,37 +169,37 @@ goto label; case 'F': - buf = _strptime(buf, "%Y-%m-%d", tm); + buf = _strptime(buf, "%Y-%m-%d", tm, flagp); if (buf == 0) return 0; break; case 'R': - buf = _strptime(buf, "%H:%M", tm); + buf = _strptime(buf, "%H:%M", tm, flagp); if (buf == 0) return 0; break; case 'r': - buf = _strptime(buf, tptr->ampm_fmt, tm); + buf = _strptime(buf, tptr->ampm_fmt, tm, flagp); if (buf == 0) return 0; break; case 'T': - buf = _strptime(buf, "%H:%M:%S", tm); + buf = _strptime(buf, "%H:%M:%S", tm, flagp); if (buf == 0) return 0; break; case 'X': - buf = _strptime(buf, tptr->X_fmt, tm); + buf = _strptime(buf, tptr->X_fmt, tm, flagp); if (buf == 0) return 0; break; case 'x': - buf = _strptime(buf, tptr->x_fmt, tm); + buf = _strptime(buf, tptr->x_fmt, tm, flagp); if (buf == 0) return 0; break; @@ -460,7 +459,7 @@ return 0; buf = cp; gmtime_r(&t, tm); - got_GMT = 1; + *flagp |= NORMALIZE_GMT; } break; @@ -504,7 +503,7 @@ zonestr[cp - buf] = '\0'; tzset(); if (0 == strcmp(zonestr, "GMT")) { - got_GMT = 1; + *flagp |= NORMALIZE_GMT; } else if (0 == strcmp(zonestr, tzname[0])) { tm->tm_isdst = 0; } else if (0 == strcmp(zonestr, tzname[1])) { @@ -516,6 +515,31 @@ } } break; + case 'z': + { + long off; + char *end; + + off = strtol(buf + 1, &end, 10); + if (end != buf + 5) + return 0; + if (off % 100 > 59) + return 0; + /* convert from 4 decimal digits to hours + minutes */ + off = (off / 100) * 60 + off % 100; + if (*buf == '-') + off = -off; + else if (*buf == '+') + off = +off; + else + return 0; + tm->tm_gmtoff = off * 60; + tm->tm_isdst = -1; + tm->tm_zone = NULL; + *flagp |= NORMALIZE_LOCAL; + buf = end; + } + break; } } return (char *)buf; @@ -526,22 +550,20 @@ strptime(const char *buf, const char *fmt, struct tm *tm) { char *ret; + int flags; -#ifdef _THREAD_SAFE - pthread_mutex_lock(&gotgmt_mutex); -#endif - - got_GMT = 0; - ret = _strptime(buf, fmt, tm); - if (ret && got_GMT) { + ret = _strptime(buf, fmt, tm, &flags); + if (ret == NULL) + return NULL; + if (flags & NORMALIZE_LOCAL) { + tm->tm_hour -= tm->tm_gmtoff / 3600; + tm->tm_min -= (tm->tm_min / 60) % 60; + flags |= NORMALIZE_GMT; + } + if (flags & NORMALIZE_GMT) { time_t t = timegm(tm); - localtime_r(&t, tm); - got_GMT = 0; + localtime_r(&t, tm); } - -#ifdef _THREAD_SAFE - pthread_mutex_unlock(&gotgmt_mutex); -#endif return ret; } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020521195107.A4260>