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.
23 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
28 * 1. Redistributions of source code must retain the above copyright
29 * notice, this list of conditions and the following disclaimer.
30 * 2. Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer
32 * in the documentation and/or other materials provided with the
34 * 3. All advertising materials mentioning features or use of this
35 * software must display the following acknowledgement:
36 * This product includes software developed by Powerdog Industries.
37 * 4. The name of Powerdog Industries may not be used to endorse or
38 * promote products derived from this software without specific prior
41 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
42 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
45 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
46 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
47 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
48 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
50 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
51 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55 static const char rcsid
[] =
56 "$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.17.2.2 2001/07/31 00:06:24 dd Exp $";
61 static char copyright
[] =
62 "@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved.";
63 static char sccsid
[] = "@(#)strptime.c 0.1 (Powerdog) 94/03/27";
64 #endif /* !defined NOID */
74 #include "pthread_private.h"
76 #include "timelocal.h"
78 static char * _strptime(const char *, const char *, struct tm
*);
81 static struct pthread_mutex _gotgmt_mutexd
= PTHREAD_MUTEX_STATIC_INITIALIZER
;
82 static pthread_mutex_t gotgmt_mutex
= &_gotgmt_mutexd
;
86 #define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
89 _strptime(const char *buf
, const char *fmt
, struct tm
*tm
)
95 int Ealternative
, Oalternative
;
105 if (isspace((unsigned char)c
))
106 while (*buf
!= 0 && isspace((unsigned char)*buf
))
108 else if (c
!= *buf
++)
125 buf
= _strptime(buf
, Locale
->date_fmt
, tm
);
131 if (!isdigit((unsigned char)*buf
))
134 /* XXX This will break for 3-digit centuries. */
136 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
144 tm
->tm_year
= i
* 100 - 1900;
148 /* NOTE: c_fmt is intentionally ignored */
149 buf
= _strptime(buf
, "%a %Ef %T %Y", tm
);
155 buf
= _strptime(buf
, "%m/%d/%y", tm
);
161 if (Ealternative
|| Oalternative
)
167 if (Ealternative
|| Oalternative
)
176 buf
= _strptime(buf
, (c
== 'f') ? Locale
->Ef_fmt
: Locale
->EF_fmt
, tm
);
182 buf
= _strptime(buf
, "%H:%M", tm
);
188 buf
= _strptime(buf
, "%I:%M:%S %p", tm
);
194 buf
= _strptime(buf
, "%H:%M:%S", tm
);
200 buf
= _strptime(buf
, Locale
->X_fmt
, tm
);
206 buf
= _strptime(buf
, Locale
->x_fmt
, tm
);
212 if (!isdigit((unsigned char)*buf
))
216 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
221 if (i
< 1 || i
> 366)
229 if (*buf
== 0 || isspace((unsigned char)*buf
))
232 if (!isdigit((unsigned char)*buf
))
236 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
252 if (*buf
!= 0 && isspace((unsigned char)*buf
))
253 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
262 * Of these, %l is the only specifier explicitly
263 * documented as not being zero-padded. However,
264 * there is no harm in allowing zero-padding.
266 * XXX The %l specifier may gobble one too many
267 * digits if used incorrectly.
269 if (!isdigit((unsigned char)*buf
))
273 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
278 if (c
== 'H' || c
== 'k') {
286 if (*buf
!= 0 && isspace((unsigned char)*buf
))
287 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
293 * XXX This is bogus if parsed before hour-related
296 len
= strlen(Locale
->am
);
297 if (strncasecmp(buf
, Locale
->am
, len
) == 0) {
298 if (tm
->tm_hour
> 12)
300 if (tm
->tm_hour
== 12)
306 len
= strlen(Locale
->pm
);
307 if (strncasecmp(buf
, Locale
->pm
, len
) == 0) {
308 if (tm
->tm_hour
> 12)
310 if (tm
->tm_hour
!= 12)
320 for (i
= 0; i
< asizeof(Locale
->weekday
); i
++) {
322 len
= strlen(Locale
->weekday
[i
]);
328 len
= strlen(Locale
->wday
[i
]);
335 if (i
== asizeof(Locale
->weekday
))
345 * XXX This is bogus, as we can not assume any valid
346 * information present in the tm structure at this
347 * point to calculate a real value, so just check the
350 if (!isdigit((unsigned char)*buf
))
354 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
362 if (*buf
!= 0 && isspace((unsigned char)*buf
))
363 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
368 if (!isdigit((unsigned char)*buf
))
377 if (*buf
!= 0 && isspace((unsigned char)*buf
))
378 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
385 * The %e specifier is explicitly documented as not
386 * being zero-padded but there is no harm in allowing
389 * XXX The %e specifier may gobble one too many
390 * digits if used incorrectly.
392 if (!isdigit((unsigned char)*buf
))
396 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
406 if (*buf
!= 0 && isspace((unsigned char)*buf
))
407 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
414 for (i
= 0; i
< asizeof(Locale
->month
); i
++) {
417 len
= strlen(Locale
->alt_month
[i
]);
419 Locale
->alt_month
[i
],
425 len
= strlen(Locale
->month
[i
]);
431 len
= strlen(Locale
->mon
[i
]);
439 if (i
== asizeof(Locale
->month
))
447 if (!isdigit((unsigned char)*buf
))
451 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
461 if (*buf
!= 0 && isspace((unsigned char)*buf
))
462 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
471 t
= strtol(buf
, &cp
, 10);
482 if (*buf
== 0 || isspace((unsigned char)*buf
))
485 if (!isdigit((unsigned char)*buf
))
488 len
= (c
== 'Y') ? 4 : 2;
489 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
496 if (c
== 'y' && i
< 69)
503 if (*buf
!= 0 && isspace((unsigned char)*buf
))
504 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
513 for (cp
= buf
; *cp
&& isupper((unsigned char)*cp
); ++cp
) {/*empty*/}
515 zonestr
= alloca(cp
- buf
+ 1);
516 strncpy(zonestr
, buf
, cp
- buf
);
517 zonestr
[cp
- buf
] = '\0';
519 if (0 == strcmp(zonestr
, "GMT")) {
521 } else if (0 == strcmp(zonestr
, tzname
[0])) {
523 } else if (0 == strcmp(zonestr
, tzname
[1])) {
539 strptime(const char *buf
, const char *fmt
, struct tm
*tm
)
544 pthread_mutex_lock(&gotgmt_mutex
);
548 ret
= _strptime(buf
, fmt
, tm
);
549 if (ret
&& got_GMT
) {
550 time_t t
= timegm(tm
);
556 pthread_mutex_unlock(&gotgmt_mutex
);