Deleted Added
full compact
strptime.c (71579) strptime.c (72168)
1/*
2 * Powerdog Industries kindly requests feedback from anyone modifying
3 * this function:
4 *
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)
9 *
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.
15 *
16 * Anyway, you can change it to "with or without modification" as
17 * you see fit. Enjoy.
18 *
19 * Kevin Ruddy
20 * Powerdog Industries, Inc.
21 */
22/*
23 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
27 * are met:
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
33 * distribution.
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
39 * written permission.
40 *
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.
52 */
53
54#ifdef LIBC_RCS
55static const char rcsid[] =
1/*
2 * Powerdog Industries kindly requests feedback from anyone modifying
3 * this function:
4 *
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)
9 *
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.
15 *
16 * Anyway, you can change it to "with or without modification" as
17 * you see fit. Enjoy.
18 *
19 * Kevin Ruddy
20 * Powerdog Industries, Inc.
21 */
22/*
23 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
27 * are met:
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
33 * distribution.
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
39 * written permission.
40 *
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.
52 */
53
54#ifdef LIBC_RCS
55static const char rcsid[] =
56 "$FreeBSD: head/lib/libc/stdtime/strptime.c 71579 2001-01-24 13:01:12Z deischen $";
56 "$FreeBSD: head/lib/libc/stdtime/strptime.c 72168 2001-02-08 17:08:13Z phantom $";
57#endif
58
59#ifndef lint
60#ifndef NOID
61static char copyright[] =
62"@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved.";
63static char sccsid[] = "@(#)strptime.c 0.1 (Powerdog) 94/03/27";
64#endif /* !defined NOID */
65#endif /* not lint */
66
67#include "namespace.h"
68#include <time.h>
69#include <ctype.h>
70#include <string.h>
71#include <pthread.h>
72#include "un-namespace.h"
73#include "libc_private.h"
74#include "timelocal.h"
75
76static char * _strptime(const char *, const char *, struct tm *);
77
78static pthread_mutex_t gotgmt_mutex = PTHREAD_MUTEX_INITIALIZER;
79static int got_GMT;
80
81#define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
82
83static char *
84_strptime(const char *buf, const char *fmt, struct tm *tm)
85{
86 char c;
87 const char *ptr;
88 int i,
89 len;
90 int Ealternative, Oalternative;
57#endif
58
59#ifndef lint
60#ifndef NOID
61static char copyright[] =
62"@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved.";
63static char sccsid[] = "@(#)strptime.c 0.1 (Powerdog) 94/03/27";
64#endif /* !defined NOID */
65#endif /* not lint */
66
67#include "namespace.h"
68#include <time.h>
69#include <ctype.h>
70#include <string.h>
71#include <pthread.h>
72#include "un-namespace.h"
73#include "libc_private.h"
74#include "timelocal.h"
75
76static char * _strptime(const char *, const char *, struct tm *);
77
78static pthread_mutex_t gotgmt_mutex = PTHREAD_MUTEX_INITIALIZER;
79static int got_GMT;
80
81#define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
82
83static char *
84_strptime(const char *buf, const char *fmt, struct tm *tm)
85{
86 char c;
87 const char *ptr;
88 int i,
89 len;
90 int Ealternative, Oalternative;
91 struct lc_time_T *tptr = __get_current_time_locale();
91
92 ptr = fmt;
93 while (*ptr != 0) {
94 if (*buf == 0)
95 break;
96
97 c = *ptr++;
98
99 if (c != '%') {
100 if (isspace((unsigned char)c))
101 while (*buf != 0 && isspace((unsigned char)*buf))
102 buf++;
103 else if (c != *buf++)
104 return 0;
105 continue;
106 }
107
108 Ealternative = 0;
109 Oalternative = 0;
110label:
111 c = *ptr++;
112 switch (c) {
113 case 0:
114 case '%':
115 if (*buf++ != '%')
116 return 0;
117 break;
118
119 case '+':
92
93 ptr = fmt;
94 while (*ptr != 0) {
95 if (*buf == 0)
96 break;
97
98 c = *ptr++;
99
100 if (c != '%') {
101 if (isspace((unsigned char)c))
102 while (*buf != 0 && isspace((unsigned char)*buf))
103 buf++;
104 else if (c != *buf++)
105 return 0;
106 continue;
107 }
108
109 Ealternative = 0;
110 Oalternative = 0;
111label:
112 c = *ptr++;
113 switch (c) {
114 case 0:
115 case '%':
116 if (*buf++ != '%')
117 return 0;
118 break;
119
120 case '+':
120 buf = _strptime(buf, Locale->date_fmt, tm);
121 buf = _strptime(buf, tptr->date_fmt, tm);
121 if (buf == 0)
122 return 0;
123 break;
124
125 case 'C':
126 if (!isdigit((unsigned char)*buf))
127 return 0;
128
129 /* XXX This will break for 3-digit centuries. */
130 len = 2;
131 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
132 i *= 10;
133 i += *buf - '0';
134 len--;
135 }
136 if (i < 19)
137 return 0;
138
139 tm->tm_year = i * 100 - 1900;
140 break;
141
142 case 'c':
143 /* NOTE: c_fmt is intentionally ignored */
144 buf = _strptime(buf, "%a %Ef %T %Y", tm);
145 if (buf == 0)
146 return 0;
147 break;
148
149 case 'D':
150 buf = _strptime(buf, "%m/%d/%y", tm);
151 if (buf == 0)
152 return 0;
153 break;
154
155 case 'E':
156 if (Ealternative || Oalternative)
157 break;
158 Ealternative++;
159 goto label;
160
161 case 'O':
162 if (Ealternative || Oalternative)
163 break;
164 Oalternative++;
165 goto label;
166
167 case 'F':
168 case 'f':
169 if (!Ealternative)
170 break;
122 if (buf == 0)
123 return 0;
124 break;
125
126 case 'C':
127 if (!isdigit((unsigned char)*buf))
128 return 0;
129
130 /* XXX This will break for 3-digit centuries. */
131 len = 2;
132 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
133 i *= 10;
134 i += *buf - '0';
135 len--;
136 }
137 if (i < 19)
138 return 0;
139
140 tm->tm_year = i * 100 - 1900;
141 break;
142
143 case 'c':
144 /* NOTE: c_fmt is intentionally ignored */
145 buf = _strptime(buf, "%a %Ef %T %Y", tm);
146 if (buf == 0)
147 return 0;
148 break;
149
150 case 'D':
151 buf = _strptime(buf, "%m/%d/%y", tm);
152 if (buf == 0)
153 return 0;
154 break;
155
156 case 'E':
157 if (Ealternative || Oalternative)
158 break;
159 Ealternative++;
160 goto label;
161
162 case 'O':
163 if (Ealternative || Oalternative)
164 break;
165 Oalternative++;
166 goto label;
167
168 case 'F':
169 case 'f':
170 if (!Ealternative)
171 break;
171 buf = _strptime(buf, (c == 'f') ? Locale->Ef_fmt : Locale->EF_fmt, tm);
172 buf = _strptime(buf, (c == 'f') ? tptr->Ef_fmt : tptr->EF_fmt, tm);
172 if (buf == 0)
173 return 0;
174 break;
175
176 case 'R':
177 buf = _strptime(buf, "%H:%M", tm);
178 if (buf == 0)
179 return 0;
180 break;
181
182 case 'r':
183 buf = _strptime(buf, "%I:%M:%S %p", tm);
184 if (buf == 0)
185 return 0;
186 break;
187
188 case 'T':
189 buf = _strptime(buf, "%H:%M:%S", tm);
190 if (buf == 0)
191 return 0;
192 break;
193
194 case 'X':
173 if (buf == 0)
174 return 0;
175 break;
176
177 case 'R':
178 buf = _strptime(buf, "%H:%M", tm);
179 if (buf == 0)
180 return 0;
181 break;
182
183 case 'r':
184 buf = _strptime(buf, "%I:%M:%S %p", tm);
185 if (buf == 0)
186 return 0;
187 break;
188
189 case 'T':
190 buf = _strptime(buf, "%H:%M:%S", tm);
191 if (buf == 0)
192 return 0;
193 break;
194
195 case 'X':
195 buf = _strptime(buf, Locale->X_fmt, tm);
196 buf = _strptime(buf, tptr->X_fmt, tm);
196 if (buf == 0)
197 return 0;
198 break;
199
200 case 'x':
197 if (buf == 0)
198 return 0;
199 break;
200
201 case 'x':
201 buf = _strptime(buf, Locale->x_fmt, tm);
202 buf = _strptime(buf, tptr->x_fmt, tm);
202 if (buf == 0)
203 return 0;
204 break;
205
206 case 'j':
207 if (!isdigit((unsigned char)*buf))
208 return 0;
209
210 len = 3;
211 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
212 i *= 10;
213 i += *buf - '0';
214 len--;
215 }
216 if (i < 1 || i > 366)
217 return 0;
218
219 tm->tm_yday = i - 1;
220 break;
221
222 case 'M':
223 case 'S':
224 if (*buf == 0 || isspace((unsigned char)*buf))
225 break;
226
227 if (!isdigit((unsigned char)*buf))
228 return 0;
229
230 len = 2;
231 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
232 i *= 10;
233 i += *buf - '0';
234 len--;
235 }
236
237 if (c == 'M') {
238 if (i > 59)
239 return 0;
240 tm->tm_min = i;
241 } else {
242 if (i > 60)
243 return 0;
244 tm->tm_sec = i;
245 }
246
247 if (*buf != 0 && isspace((unsigned char)*buf))
248 while (*ptr != 0 && !isspace((unsigned char)*ptr))
249 ptr++;
250 break;
251
252 case 'H':
253 case 'I':
254 case 'k':
255 case 'l':
256 /*
257 * Of these, %l is the only specifier explicitly
258 * documented as not being zero-padded. However,
259 * there is no harm in allowing zero-padding.
260 *
261 * XXX The %l specifier may gobble one too many
262 * digits if used incorrectly.
263 */
264 if (!isdigit((unsigned char)*buf))
265 return 0;
266
267 len = 2;
268 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
269 i *= 10;
270 i += *buf - '0';
271 len--;
272 }
273 if (c == 'H' || c == 'k') {
274 if (i > 23)
275 return 0;
276 } else if (i > 12)
277 return 0;
278
279 tm->tm_hour = i;
280
281 if (*buf != 0 && isspace((unsigned char)*buf))
282 while (*ptr != 0 && !isspace((unsigned char)*ptr))
283 ptr++;
284 break;
285
286 case 'p':
287 /*
288 * XXX This is bogus if parsed before hour-related
289 * specifiers.
290 */
203 if (buf == 0)
204 return 0;
205 break;
206
207 case 'j':
208 if (!isdigit((unsigned char)*buf))
209 return 0;
210
211 len = 3;
212 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
213 i *= 10;
214 i += *buf - '0';
215 len--;
216 }
217 if (i < 1 || i > 366)
218 return 0;
219
220 tm->tm_yday = i - 1;
221 break;
222
223 case 'M':
224 case 'S':
225 if (*buf == 0 || isspace((unsigned char)*buf))
226 break;
227
228 if (!isdigit((unsigned char)*buf))
229 return 0;
230
231 len = 2;
232 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
233 i *= 10;
234 i += *buf - '0';
235 len--;
236 }
237
238 if (c == 'M') {
239 if (i > 59)
240 return 0;
241 tm->tm_min = i;
242 } else {
243 if (i > 60)
244 return 0;
245 tm->tm_sec = i;
246 }
247
248 if (*buf != 0 && isspace((unsigned char)*buf))
249 while (*ptr != 0 && !isspace((unsigned char)*ptr))
250 ptr++;
251 break;
252
253 case 'H':
254 case 'I':
255 case 'k':
256 case 'l':
257 /*
258 * Of these, %l is the only specifier explicitly
259 * documented as not being zero-padded. However,
260 * there is no harm in allowing zero-padding.
261 *
262 * XXX The %l specifier may gobble one too many
263 * digits if used incorrectly.
264 */
265 if (!isdigit((unsigned char)*buf))
266 return 0;
267
268 len = 2;
269 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
270 i *= 10;
271 i += *buf - '0';
272 len--;
273 }
274 if (c == 'H' || c == 'k') {
275 if (i > 23)
276 return 0;
277 } else if (i > 12)
278 return 0;
279
280 tm->tm_hour = i;
281
282 if (*buf != 0 && isspace((unsigned char)*buf))
283 while (*ptr != 0 && !isspace((unsigned char)*ptr))
284 ptr++;
285 break;
286
287 case 'p':
288 /*
289 * XXX This is bogus if parsed before hour-related
290 * specifiers.
291 */
291 len = strlen(Locale->am);
292 if (strncasecmp(buf, Locale->am, len) == 0) {
292 len = strlen(tptr->am);
293 if (strncasecmp(buf, tptr->am, len) == 0) {
293 if (tm->tm_hour > 12)
294 return 0;
295 if (tm->tm_hour == 12)
296 tm->tm_hour = 0;
297 buf += len;
298 break;
299 }
300
294 if (tm->tm_hour > 12)
295 return 0;
296 if (tm->tm_hour == 12)
297 tm->tm_hour = 0;
298 buf += len;
299 break;
300 }
301
301 len = strlen(Locale->pm);
302 if (strncasecmp(buf, Locale->pm, len) == 0) {
302 len = strlen(tptr->pm);
303 if (strncasecmp(buf, tptr->pm, len) == 0) {
303 if (tm->tm_hour > 12)
304 return 0;
305 if (tm->tm_hour != 12)
306 tm->tm_hour += 12;
307 buf += len;
308 break;
309 }
310
311 return 0;
312
313 case 'A':
314 case 'a':
304 if (tm->tm_hour > 12)
305 return 0;
306 if (tm->tm_hour != 12)
307 tm->tm_hour += 12;
308 buf += len;
309 break;
310 }
311
312 return 0;
313
314 case 'A':
315 case 'a':
315 for (i = 0; i < asizeof(Locale->weekday); i++) {
316 for (i = 0; i < asizeof(tptr->weekday); i++) {
316 if (c == 'A') {
317 if (c == 'A') {
317 len = strlen(Locale->weekday[i]);
318 len = strlen(tptr->weekday[i]);
318 if (strncasecmp(buf,
319 if (strncasecmp(buf,
319 Locale->weekday[i],
320 tptr->weekday[i],
320 len) == 0)
321 break;
322 } else {
321 len) == 0)
322 break;
323 } else {
323 len = strlen(Locale->wday[i]);
324 len = strlen(tptr->wday[i]);
324 if (strncasecmp(buf,
325 if (strncasecmp(buf,
325 Locale->wday[i],
326 tptr->wday[i],
326 len) == 0)
327 break;
328 }
329 }
327 len) == 0)
328 break;
329 }
330 }
330 if (i == asizeof(Locale->weekday))
331 if (i == asizeof(tptr->weekday))
331 return 0;
332
333 tm->tm_wday = i;
334 buf += len;
335 break;
336
337 case 'U':
338 case 'W':
339 /*
340 * XXX This is bogus, as we can not assume any valid
341 * information present in the tm structure at this
342 * point to calculate a real value, so just check the
343 * range for now.
344 */
345 if (!isdigit((unsigned char)*buf))
346 return 0;
347
348 len = 2;
349 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
350 i *= 10;
351 i += *buf - '0';
352 len--;
353 }
354 if (i > 53)
355 return 0;
356
357 if (*buf != 0 && isspace((unsigned char)*buf))
358 while (*ptr != 0 && !isspace((unsigned char)*ptr))
359 ptr++;
360 break;
361
362 case 'w':
363 if (!isdigit((unsigned char)*buf))
364 return 0;
365
366 i = *buf - '0';
367 if (i > 6)
368 return 0;
369
370 tm->tm_wday = i;
371
372 if (*buf != 0 && isspace((unsigned char)*buf))
373 while (*ptr != 0 && !isspace((unsigned char)*ptr))
374 ptr++;
375 break;
376
377 case 'd':
378 case 'e':
379 /*
380 * The %e specifier is explicitly documented as not
381 * being zero-padded but there is no harm in allowing
382 * such padding.
383 *
384 * XXX The %e specifier may gobble one too many
385 * digits if used incorrectly.
386 */
387 if (!isdigit((unsigned char)*buf))
388 return 0;
389
390 len = 2;
391 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
392 i *= 10;
393 i += *buf - '0';
394 len--;
395 }
396 if (i > 31)
397 return 0;
398
399 tm->tm_mday = i;
400
401 if (*buf != 0 && isspace((unsigned char)*buf))
402 while (*ptr != 0 && !isspace((unsigned char)*ptr))
403 ptr++;
404 break;
405
406 case 'B':
407 case 'b':
408 case 'h':
332 return 0;
333
334 tm->tm_wday = i;
335 buf += len;
336 break;
337
338 case 'U':
339 case 'W':
340 /*
341 * XXX This is bogus, as we can not assume any valid
342 * information present in the tm structure at this
343 * point to calculate a real value, so just check the
344 * range for now.
345 */
346 if (!isdigit((unsigned char)*buf))
347 return 0;
348
349 len = 2;
350 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
351 i *= 10;
352 i += *buf - '0';
353 len--;
354 }
355 if (i > 53)
356 return 0;
357
358 if (*buf != 0 && isspace((unsigned char)*buf))
359 while (*ptr != 0 && !isspace((unsigned char)*ptr))
360 ptr++;
361 break;
362
363 case 'w':
364 if (!isdigit((unsigned char)*buf))
365 return 0;
366
367 i = *buf - '0';
368 if (i > 6)
369 return 0;
370
371 tm->tm_wday = i;
372
373 if (*buf != 0 && isspace((unsigned char)*buf))
374 while (*ptr != 0 && !isspace((unsigned char)*ptr))
375 ptr++;
376 break;
377
378 case 'd':
379 case 'e':
380 /*
381 * The %e specifier is explicitly documented as not
382 * being zero-padded but there is no harm in allowing
383 * such padding.
384 *
385 * XXX The %e specifier may gobble one too many
386 * digits if used incorrectly.
387 */
388 if (!isdigit((unsigned char)*buf))
389 return 0;
390
391 len = 2;
392 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
393 i *= 10;
394 i += *buf - '0';
395 len--;
396 }
397 if (i > 31)
398 return 0;
399
400 tm->tm_mday = i;
401
402 if (*buf != 0 && isspace((unsigned char)*buf))
403 while (*ptr != 0 && !isspace((unsigned char)*ptr))
404 ptr++;
405 break;
406
407 case 'B':
408 case 'b':
409 case 'h':
409 for (i = 0; i < asizeof(Locale->month); i++) {
410 for (i = 0; i < asizeof(tptr->month); i++) {
410 if (Oalternative) {
411 if (c == 'B') {
411 if (Oalternative) {
412 if (c == 'B') {
412 len = strlen(Locale->alt_month[i]);
413 len = strlen(tptr->alt_month[i]);
413 if (strncasecmp(buf,
414 if (strncasecmp(buf,
414 Locale->alt_month[i],
415 tptr->alt_month[i],
415 len) == 0)
416 break;
417 }
418 } else {
419 if (c == 'B') {
416 len) == 0)
417 break;
418 }
419 } else {
420 if (c == 'B') {
420 len = strlen(Locale->month[i]);
421 len = strlen(tptr->month[i]);
421 if (strncasecmp(buf,
422 if (strncasecmp(buf,
422 Locale->month[i],
423 tptr->month[i],
423 len) == 0)
424 break;
425 } else {
424 len) == 0)
425 break;
426 } else {
426 len = strlen(Locale->mon[i]);
427 len = strlen(tptr->mon[i]);
427 if (strncasecmp(buf,
428 if (strncasecmp(buf,
428 Locale->mon[i],
429 tptr->mon[i],
429 len) == 0)
430 break;
431 }
432 }
433 }
430 len) == 0)
431 break;
432 }
433 }
434 }
434 if (i == asizeof(Locale->month))
435 if (i == asizeof(tptr->month))
435 return 0;
436
437 tm->tm_mon = i;
438 buf += len;
439 break;
440
441 case 'm':
442 if (!isdigit((unsigned char)*buf))
443 return 0;
444
445 len = 2;
446 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
447 i *= 10;
448 i += *buf - '0';
449 len--;
450 }
451 if (i < 1 || i > 12)
452 return 0;
453
454 tm->tm_mon = i - 1;
455
456 if (*buf != 0 && isspace((unsigned char)*buf))
457 while (*ptr != 0 && !isspace((unsigned char)*ptr))
458 ptr++;
459 break;
460
461 case 'Y':
462 case 'y':
463 if (*buf == 0 || isspace((unsigned char)*buf))
464 break;
465
466 if (!isdigit((unsigned char)*buf))
467 return 0;
468
469 len = (c == 'Y') ? 4 : 2;
470 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
471 i *= 10;
472 i += *buf - '0';
473 len--;
474 }
475 if (c == 'Y')
476 i -= 1900;
477 if (c == 'y' && i < 69)
478 i += 100;
479 if (i < 0)
480 return 0;
481
482 tm->tm_year = i;
483
484 if (*buf != 0 && isspace((unsigned char)*buf))
485 while (*ptr != 0 && !isspace((unsigned char)*ptr))
486 ptr++;
487 break;
488
489 case 'Z':
490 {
491 const char *cp;
492 char *zonestr;
493
494 for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/}
495 if (cp - buf) {
496 zonestr = alloca(cp - buf + 1);
497 strncpy(zonestr, buf, cp - buf);
498 zonestr[cp - buf] = '\0';
499 tzset();
500 if (0 == strcmp(zonestr, "GMT")) {
501 got_GMT = 1;
502 } else if (0 == strcmp(zonestr, tzname[0])) {
503 tm->tm_isdst = 0;
504 } else if (0 == strcmp(zonestr, tzname[1])) {
505 tm->tm_isdst = 1;
506 } else {
507 return 0;
508 }
509 buf += cp - buf;
510 }
511 }
512 break;
513 }
514 }
515 return (char *)buf;
516}
517
518
519char *
520strptime(const char *buf, const char *fmt, struct tm *tm)
521{
522 char *ret;
523
524 if (__isthreaded)
525 _pthread_mutex_lock(&gotgmt_mutex);
526
527 got_GMT = 0;
528 ret = _strptime(buf, fmt, tm);
529 if (ret && got_GMT) {
530 time_t t = timegm(tm);
531 localtime_r(&t, tm);
532 got_GMT = 0;
533 }
534
535 if (__isthreaded)
536 _pthread_mutex_unlock(&gotgmt_mutex);
537
538 return ret;
539}
436 return 0;
437
438 tm->tm_mon = i;
439 buf += len;
440 break;
441
442 case 'm':
443 if (!isdigit((unsigned char)*buf))
444 return 0;
445
446 len = 2;
447 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
448 i *= 10;
449 i += *buf - '0';
450 len--;
451 }
452 if (i < 1 || i > 12)
453 return 0;
454
455 tm->tm_mon = i - 1;
456
457 if (*buf != 0 && isspace((unsigned char)*buf))
458 while (*ptr != 0 && !isspace((unsigned char)*ptr))
459 ptr++;
460 break;
461
462 case 'Y':
463 case 'y':
464 if (*buf == 0 || isspace((unsigned char)*buf))
465 break;
466
467 if (!isdigit((unsigned char)*buf))
468 return 0;
469
470 len = (c == 'Y') ? 4 : 2;
471 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
472 i *= 10;
473 i += *buf - '0';
474 len--;
475 }
476 if (c == 'Y')
477 i -= 1900;
478 if (c == 'y' && i < 69)
479 i += 100;
480 if (i < 0)
481 return 0;
482
483 tm->tm_year = i;
484
485 if (*buf != 0 && isspace((unsigned char)*buf))
486 while (*ptr != 0 && !isspace((unsigned char)*ptr))
487 ptr++;
488 break;
489
490 case 'Z':
491 {
492 const char *cp;
493 char *zonestr;
494
495 for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/}
496 if (cp - buf) {
497 zonestr = alloca(cp - buf + 1);
498 strncpy(zonestr, buf, cp - buf);
499 zonestr[cp - buf] = '\0';
500 tzset();
501 if (0 == strcmp(zonestr, "GMT")) {
502 got_GMT = 1;
503 } else if (0 == strcmp(zonestr, tzname[0])) {
504 tm->tm_isdst = 0;
505 } else if (0 == strcmp(zonestr, tzname[1])) {
506 tm->tm_isdst = 1;
507 } else {
508 return 0;
509 }
510 buf += cp - buf;
511 }
512 }
513 break;
514 }
515 }
516 return (char *)buf;
517}
518
519
520char *
521strptime(const char *buf, const char *fmt, struct tm *tm)
522{
523 char *ret;
524
525 if (__isthreaded)
526 _pthread_mutex_lock(&gotgmt_mutex);
527
528 got_GMT = 0;
529 ret = _strptime(buf, fmt, tm);
530 if (ret && got_GMT) {
531 time_t t = timegm(tm);
532 localtime_r(&t, tm);
533 got_GMT = 0;
534 }
535
536 if (__isthreaded)
537 _pthread_mutex_unlock(&gotgmt_mutex);
538
539 return ret;
540}