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.
54 #include <sys/cdefs.h>
57 static char copyright[] __unused =
58 "@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved.";
59 static char sccsid[] __unused = "@(#)strptime.c 0.1 (Powerdog) 94/03/27";
60 #endif /* !defined NOID */
62 __FBSDID("$FreeBSD$");
64 #include "namespace.h"
71 #include "un-namespace.h"
72 #include "libc_private.h"
73 #include "timelocal.h"
75 static char * _strptime(const char *, const char *, struct tm *, int *);
77 #define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
80 _strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp)
86 int Ealternative, Oalternative;
87 struct lc_time_T *tptr = __get_current_time_locale();
97 if (isspace((unsigned char)c))
98 while (*buf != 0 && isspace((unsigned char)*buf))
100 else if (c != *buf++)
117 buf = _strptime(buf, tptr->date_fmt, tm, GMTp);
123 if (!isdigit((unsigned char)*buf))
126 /* XXX This will break for 3-digit centuries. */
128 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
136 tm->tm_year = i * 100 - 1900;
140 buf = _strptime(buf, tptr->c_fmt, tm, GMTp);
146 buf = _strptime(buf, "%m/%d/%y", tm, GMTp);
152 if (Ealternative || Oalternative)
158 if (Ealternative || Oalternative)
164 buf = _strptime(buf, "%Y-%m-%d", tm, GMTp);
170 buf = _strptime(buf, "%H:%M", tm, GMTp);
176 buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp);
182 buf = _strptime(buf, "%H:%M:%S", tm, GMTp);
188 buf = _strptime(buf, tptr->X_fmt, tm, GMTp);
194 buf = _strptime(buf, tptr->x_fmt, tm, GMTp);
200 if (!isdigit((unsigned char)*buf))
204 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
209 if (i < 1 || i > 366)
217 if (*buf == 0 || isspace((unsigned char)*buf))
220 if (!isdigit((unsigned char)*buf))
224 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
240 if (*buf != 0 && isspace((unsigned char)*buf))
241 while (*ptr != 0 && !isspace((unsigned char)*ptr))
250 * Of these, %l is the only specifier explicitly
251 * documented as not being zero-padded. However,
252 * there is no harm in allowing zero-padding.
254 * XXX The %l specifier may gobble one too many
255 * digits if used incorrectly.
257 if (!isdigit((unsigned char)*buf))
261 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
266 if (c == 'H' || c == 'k') {
274 if (*buf != 0 && isspace((unsigned char)*buf))
275 while (*ptr != 0 && !isspace((unsigned char)*ptr))
281 * XXX This is bogus if parsed before hour-related
284 len = strlen(tptr->am);
285 if (strncasecmp(buf, tptr->am, len) == 0) {
286 if (tm->tm_hour > 12)
288 if (tm->tm_hour == 12)
294 len = strlen(tptr->pm);
295 if (strncasecmp(buf, tptr->pm, len) == 0) {
296 if (tm->tm_hour > 12)
298 if (tm->tm_hour != 12)
308 for (i = 0; i < asizeof(tptr->weekday); i++) {
309 len = strlen(tptr->weekday[i]);
310 if (strncasecmp(buf, tptr->weekday[i],
313 len = strlen(tptr->wday[i]);
314 if (strncasecmp(buf, tptr->wday[i],
318 if (i == asizeof(tptr->weekday))
328 * XXX This is bogus, as we can not assume any valid
329 * information present in the tm structure at this
330 * point to calculate a real value, so just check the
333 if (!isdigit((unsigned char)*buf))
337 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
345 if (*buf != 0 && isspace((unsigned char)*buf))
346 while (*ptr != 0 && !isspace((unsigned char)*ptr))
351 if (!isdigit((unsigned char)*buf))
360 if (*buf != 0 && isspace((unsigned char)*buf))
361 while (*ptr != 0 && !isspace((unsigned char)*ptr))
368 * The %e specifier is explicitly documented as not
369 * being zero-padded but there is no harm in allowing
372 * XXX The %e specifier may gobble one too many
373 * digits if used incorrectly.
375 if (!isdigit((unsigned char)*buf))
379 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
389 if (*buf != 0 && isspace((unsigned char)*buf))
390 while (*ptr != 0 && !isspace((unsigned char)*ptr))
397 for (i = 0; i < asizeof(tptr->month); i++) {
400 len = strlen(tptr->alt_month[i]);
407 len = strlen(tptr->month[i]);
408 if (strncasecmp(buf, tptr->month[i],
411 len = strlen(tptr->mon[i]);
412 if (strncasecmp(buf, tptr->mon[i],
417 if (i == asizeof(tptr->month))
425 if (!isdigit((unsigned char)*buf))
429 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
439 if (*buf != 0 && isspace((unsigned char)*buf))
440 while (*ptr != 0 && !isspace((unsigned char)*ptr))
453 n = strtol(buf, &cp, 10);
454 if (errno == ERANGE || (long)(t = n) != n) {
467 if (*buf == 0 || isspace((unsigned char)*buf))
470 if (!isdigit((unsigned char)*buf))
473 len = (c == 'Y') ? 4 : 2;
474 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
481 if (c == 'y' && i < 69)
488 if (*buf != 0 && isspace((unsigned char)*buf))
489 while (*ptr != 0 && !isspace((unsigned char)*ptr))
498 for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/}
500 zonestr = alloca(cp - buf + 1);
501 strncpy(zonestr, buf, cp - buf);
502 zonestr[cp - buf] = '\0';
504 if (0 == strcmp(zonestr, "GMT")) {
506 } else if (0 == strcmp(zonestr, tzname[0])) {
508 } else if (0 == strcmp(zonestr, tzname[1])) {
524 strptime(const char * __restrict buf, const char * __restrict fmt,
525 struct tm * __restrict tm)
531 ret = _strptime(buf, fmt, tm, &gmt);
533 time_t t = timegm(tm);