2 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer
11 * in the documentation and/or other materials provided with the
13 * 3. All advertising materials mentioning features or use of this
14 * software must display the following acknowledgement:
15 * This product includes software developed by Powerdog Industries.
16 * 4. The name of Powerdog Industries may not be used to endorse or
17 * promote products derived from this software without specific prior
20 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include "timelocal.h"
40 #include <errno_private.h>
42 static char * _strptime(const char *, const char *, struct tm
*, int *);
44 #define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
47 _strptime(const char *buf
, const char *fmt
, struct tm
*tm
, int *GMTp
)
53 int Ealternative
, Oalternative
;
54 struct lc_time_t
*tptr
= __get_current_time_locale();
64 if (isspace((unsigned char)c
))
65 while (*buf
!= 0 && isspace((unsigned char)*buf
))
84 buf
= _strptime(buf
, tptr
->date_fmt
, tm
, GMTp
);
90 if (!isdigit((unsigned char)*buf
))
93 /* XXX This will break for 3-digit centuries. */
95 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
103 tm
->tm_year
= i
* 100 - 1900;
107 buf
= _strptime(buf
, tptr
->c_fmt
, tm
, GMTp
);
113 buf
= _strptime(buf
, "%m/%d/%y", tm
, GMTp
);
119 if (Ealternative
|| Oalternative
)
125 if (Ealternative
|| Oalternative
)
131 buf
= _strptime(buf
, "%Y-%m-%d", tm
, GMTp
);
137 buf
= _strptime(buf
, "%H:%M", tm
, GMTp
);
143 buf
= _strptime(buf
, tptr
->ampm_fmt
, tm
, GMTp
);
149 buf
= _strptime(buf
, "%H:%M:%S", tm
, GMTp
);
155 buf
= _strptime(buf
, tptr
->X_fmt
, tm
, GMTp
);
161 buf
= _strptime(buf
, tptr
->x_fmt
, tm
, GMTp
);
167 if (!isdigit((unsigned char)*buf
))
171 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
176 if (i
< 1 || i
> 366)
184 if (*buf
== 0 || isspace((unsigned char)*buf
))
187 if (!isdigit((unsigned char)*buf
))
191 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
207 if (*buf
!= 0 && isspace((unsigned char)*buf
))
208 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
217 * Of these, %l is the only specifier explicitly
218 * documented as not being zero-padded. However,
219 * there is no harm in allowing zero-padding.
221 * XXX The %l specifier may gobble one too many
222 * digits if used incorrectly.
224 if (!isdigit((unsigned char)*buf
))
228 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
233 if (c
== 'H' || c
== 'k') {
241 if (*buf
!= 0 && isspace((unsigned char)*buf
))
242 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
248 * XXX This is bogus if parsed before hour-related
251 len
= strlen(tptr
->am
);
252 if (strncasecmp(buf
, tptr
->am
, len
) == 0) {
253 if (tm
->tm_hour
> 12)
255 if (tm
->tm_hour
== 12)
261 len
= strlen(tptr
->pm
);
262 if (strncasecmp(buf
, tptr
->pm
, len
) == 0) {
263 if (tm
->tm_hour
> 12)
265 if (tm
->tm_hour
!= 12)
275 for (i
= 0; i
< asizeof(tptr
->weekday
); i
++) {
276 len
= strlen(tptr
->weekday
[i
]);
277 if (strncasecmp(buf
, tptr
->weekday
[i
],
280 len
= strlen(tptr
->wday
[i
]);
281 if (strncasecmp(buf
, tptr
->wday
[i
],
285 if (i
== asizeof(tptr
->weekday
))
295 * XXX This is bogus, as we can not assume any valid
296 * information present in the tm structure at this
297 * point to calculate a real value, so just check the
300 if (!isdigit((unsigned char)*buf
))
304 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
312 if (*buf
!= 0 && isspace((unsigned char)*buf
))
313 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
318 if (!isdigit((unsigned char)*buf
))
327 if (*buf
!= 0 && isspace((unsigned char)*buf
))
328 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
335 * The %e specifier is explicitly documented as not
336 * being zero-padded but there is no harm in allowing
339 * XXX The %e specifier may gobble one too many
340 * digits if used incorrectly.
342 if (!isdigit((unsigned char)*buf
))
346 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
356 if (*buf
!= 0 && isspace((unsigned char)*buf
))
357 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
364 for (i
= 0; i
< asizeof(tptr
->month
); i
++) {
367 len
= strlen(tptr
->alt_month
[i
]);
374 len
= strlen(tptr
->month
[i
]);
375 if (strncasecmp(buf
, tptr
->month
[i
],
378 len
= strlen(tptr
->mon
[i
]);
379 if (strncasecmp(buf
, tptr
->mon
[i
],
384 if (i
== asizeof(tptr
->month
))
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
))
420 n
= strtol(buf
, &cp
, 10);
421 if (errno
== ERANGE
|| (long)(t
= n
) != n
) {
422 __set_errno(sverrno
);
425 __set_errno(sverrno
);
434 if (*buf
== 0 || isspace((unsigned char)*buf
))
437 if (!isdigit((unsigned char)*buf
))
440 len
= (c
== 'Y') ? 4 : 2;
441 for (i
= 0; len
&& *buf
!= 0 && isdigit((unsigned char)*buf
); buf
++) {
448 if (c
== 'y' && i
< 69)
453 if (*buf
!= 0 && isspace((unsigned char)*buf
))
454 while (*ptr
!= 0 && !isspace((unsigned char)*ptr
))
463 for (cp
= buf
; *cp
&& isupper((unsigned char)*cp
); ++cp
) {/*empty*/}
465 zonestr
= alloca(cp
- buf
+ 1);
466 strncpy(zonestr
, buf
, cp
- buf
);
467 zonestr
[cp
- buf
] = '\0';
469 if (0 == strcmp(zonestr
, "GMT")) {
471 } else if (0 == strcmp(zonestr
, tzname
[0])) {
473 } else if (0 == strcmp(zonestr
, tzname
[1])) {
489 strptime(const char * __restrict buf
, const char * __restrict fmt
,
490 struct tm
* __restrict tm
)
496 ret
= _strptime(buf
, fmt
, tm
, &gmt
);
498 time_t t
= timegm(tm
);