2 * Powerdog Industries kindly requests feedback from anyone modifying
5 * Date: Thu, 05 Jun 1997 23:17:17 -0400
6 * From: Kevin Ruddy <kevin.ruddy@powerdog.com>
7 * To: James FitzGibbon <james@nexis.net>
8 * Subject: Re: Use of your strptime(3) code (fwd)
10 * The reason for the "no mod" clause was so that modifications would
11 * come back and we could integrate them and reissue so that a wider
12 * audience could use it (thereby spreading the wealth). This has
13 * made it possible to get strptime to work on many operating systems.
14 * I'm not sure why that's "plain unacceptable" to the FreeBSD team.
16 * Anyway, you can change it to "with or without modification" as
20 * Powerdog Industries, Inc.
22 * @(#) Copyright (c) 1994 Powerdog Industries. All rights reserved.
23 * @(#)strptime.c 0.1 (Powerdog) 94/03/27
24 * $FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.17.2.3 2002/03/12 17:24:54 phantom Exp $
25 * $DragonFly: src/lib/libcr/stdtime/Attic/strptime.c,v 1.2 2003/06/17 04:26:46 dillon Exp $
28 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer
37 * in the documentation and/or other materials provided with the
39 * 3. All advertising materials mentioning features or use of this
40 * software must display the following acknowledgement:
41 * This product includes software developed by Powerdog Industries.
42 * 4. The name of Powerdog Industries may not be used to endorse or
43 * promote products derived from this software without specific prior
46 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
47 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
50 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
53 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
54 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
55 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
56 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
66 #include "pthread_private.h"
68 #include "timelocal.h"
70 static char * _strptime(const char *, const char *, struct tm *);
73 static struct pthread_mutex _gotgmt_mutexd = PTHREAD_MUTEX_STATIC_INITIALIZER;
74 static pthread_mutex_t gotgmt_mutex = &_gotgmt_mutexd;
78 #define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
81 _strptime(const char *buf, const char *fmt, struct tm *tm)
87 int Ealternative, Oalternative;
88 struct lc_time_T *tptr = __get_current_time_locale();
98 if (isspace((unsigned char)c))
99 while (*buf != 0 && isspace((unsigned char)*buf))
101 else if (c != *buf++)
118 buf = _strptime(buf, tptr->date_fmt, tm);
124 if (!isdigit((unsigned char)*buf))
127 /* XXX This will break for 3-digit centuries. */
129 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
137 tm->tm_year = i * 100 - 1900;
141 buf = _strptime(buf, tptr->c_fmt, tm);
147 buf = _strptime(buf, "%m/%d/%y", tm);
153 if (Ealternative || Oalternative)
159 if (Ealternative || Oalternative)
165 buf = _strptime(buf, "%Y-%m-%d", tm);
171 buf = _strptime(buf, "%H:%M", tm);
177 buf = _strptime(buf, tptr->ampm_fmt, tm);
183 buf = _strptime(buf, "%H:%M:%S", tm);
189 buf = _strptime(buf, tptr->X_fmt, tm);
195 buf = _strptime(buf, tptr->x_fmt, tm);
201 if (!isdigit((unsigned char)*buf))
205 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
210 if (i < 1 || i > 366)
218 if (*buf == 0 || isspace((unsigned char)*buf))
221 if (!isdigit((unsigned char)*buf))
225 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
241 if (*buf != 0 && isspace((unsigned char)*buf))
242 while (*ptr != 0 && !isspace((unsigned char)*ptr))
251 * Of these, %l is the only specifier explicitly
252 * documented as not being zero-padded. However,
253 * there is no harm in allowing zero-padding.
255 * XXX The %l specifier may gobble one too many
256 * digits if used incorrectly.
258 if (!isdigit((unsigned char)*buf))
262 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
267 if (c == 'H' || c == 'k') {
275 if (*buf != 0 && isspace((unsigned char)*buf))
276 while (*ptr != 0 && !isspace((unsigned char)*ptr))
282 * XXX This is bogus if parsed before hour-related
285 len = strlen(tptr->am);
286 if (strncasecmp(buf, tptr->am, len) == 0) {
287 if (tm->tm_hour > 12)
289 if (tm->tm_hour == 12)
295 len = strlen(tptr->pm);
296 if (strncasecmp(buf, tptr->pm, len) == 0) {
297 if (tm->tm_hour > 12)
299 if (tm->tm_hour != 12)
309 for (i = 0; i < asizeof(tptr->weekday); i++) {
310 len = strlen(tptr->weekday[i]);
311 if (strncasecmp(buf, tptr->weekday[i],
314 len = strlen(tptr->wday[i]);
315 if (strncasecmp(buf, tptr->wday[i],
319 if (i == asizeof(tptr->weekday))
329 * XXX This is bogus, as we can not assume any valid
330 * information present in the tm structure at this
331 * point to calculate a real value, so just check the
334 if (!isdigit((unsigned char)*buf))
338 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
346 if (*buf != 0 && isspace((unsigned char)*buf))
347 while (*ptr != 0 && !isspace((unsigned char)*ptr))
352 if (!isdigit((unsigned char)*buf))
361 if (*buf != 0 && isspace((unsigned char)*buf))
362 while (*ptr != 0 && !isspace((unsigned char)*ptr))
369 * The %e specifier is explicitly documented as not
370 * being zero-padded but there is no harm in allowing
373 * XXX The %e specifier may gobble one too many
374 * digits if used incorrectly.
376 if (!isdigit((unsigned char)*buf))
380 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
390 if (*buf != 0 && isspace((unsigned char)*buf))
391 while (*ptr != 0 && !isspace((unsigned char)*ptr))
398 for (i = 0; i < asizeof(tptr->month); i++) {
401 len = strlen(tptr->alt_month[i]);
408 len = strlen(tptr->month[i]);
409 if (strncasecmp(buf, tptr->month[i],
412 len = strlen(tptr->mon[i]);
413 if (strncasecmp(buf, tptr->mon[i],
418 if (i == asizeof(tptr->month))
426 if (!isdigit((unsigned char)*buf))
430 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
440 if (*buf != 0 && isspace((unsigned char)*buf))
441 while (*ptr != 0 && !isspace((unsigned char)*ptr))
450 t = strtol(buf, &cp, 10);
461 if (*buf == 0 || isspace((unsigned char)*buf))
464 if (!isdigit((unsigned char)*buf))
467 len = (c == 'Y') ? 4 : 2;
468 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
475 if (c == 'y' && i < 69)
482 if (*buf != 0 && isspace((unsigned char)*buf))
483 while (*ptr != 0 && !isspace((unsigned char)*ptr))
492 for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/}
494 zonestr = alloca(cp - buf + 1);
495 strncpy(zonestr, buf, cp - buf);
496 zonestr[cp - buf] = '\0';
498 if (0 == strcmp(zonestr, "GMT")) {
500 } else if (0 == strcmp(zonestr, tzname[0])) {
502 } else if (0 == strcmp(zonestr, tzname[1])) {
518 strptime(const char *buf, const char *fmt, struct tm *tm)
523 pthread_mutex_lock(&gotgmt_mutex);
527 ret = _strptime(buf, fmt, tm);
528 if (ret && got_GMT) {
529 time_t t = timegm(tm);
535 pthread_mutex_unlock(&gotgmt_mutex);