blob: 41eaa9b42b94096e8ed115bea542f06f61efa354 [file] [log] [blame]
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -07001/* $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $ */
2/* $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $ */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003
4/*-
5 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code was contributed to The NetBSD Foundation by Klaus Klein.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39//#include <sys/localedef.h>
40#include <ctype.h>
Elliott Hughes81baaf22018-02-28 15:22:48 -080041#include <errno.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080042#include <locale.h>
Elliott Hughes81baaf22018-02-28 15:22:48 -080043#include <stdlib.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080044#include <string.h>
45#include <time.h>
46#include "tzfile.h"
47
48static const struct {
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -070049 const char *abday[7];
50 const char *day[7];
51 const char *abmon[12];
52 const char *mon[12];
53 const char *am_pm[2];
54 const char *d_t_fmt;
55 const char *d_fmt;
56 const char *t_fmt;
57 const char *t_fmt_ampm;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080058} _DefaultTimeLocale = {
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -070059 {
60 "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
61 },
62 {
63 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
64 "Friday", "Saturday"
65 },
66 {
67 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
68 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
69 },
70 {
71 "January", "February", "March", "April", "May", "June", "July",
72 "August", "September", "October", "November", "December"
73 },
74 {
75 "AM", "PM"
76 },
77 "%a %b %d %H:%M:%S %Y",
78 "%m/%d/%y",
79 "%H:%M:%S",
80 "%I:%M:%S %p"
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080081};
82
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -070083#define _ctloc(x) (_DefaultTimeLocale.x)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080084
85/*
86 * We do not implement alternate representations. However, we always
87 * check whether a given modifier is allowed for a certain conversion.
88 */
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -070089#define _ALT_E 0x01
90#define _ALT_O 0x02
91#define _LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080092
93
Glenn Kastenb138e4f2011-01-09 10:33:23 -080094struct century_relyear {
95 int century;
96 int relyear;
97};
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -070098static int _conv_num(const unsigned char **, int *, int, int);
Glenn Kastenb138e4f2011-01-09 10:33:23 -080099static unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
100 struct century_relyear *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800101
102
103char *
104strptime(const char *buf, const char *fmt, struct tm *tm)
105{
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800106 struct century_relyear cr;
107 cr.century = TM_YEAR_BASE;
108 cr.relyear = -1;
109 return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800110}
111
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700112static unsigned char *
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800113_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800114{
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700115 unsigned char c;
116 const unsigned char *bp;
117 size_t len = 0;
118 int alt_format, i;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800119
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700120 bp = (unsigned char *)buf;
121 while ((c = *fmt) != '\0') {
122 /* Clear `alternate' modifier prior to new conversion. */
123 alt_format = 0;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800124
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700125 /* Eat up white-space. */
126 if (isspace(c)) {
127 while (isspace(*bp))
128 bp++;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800129
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700130 fmt++;
131 continue;
132 }
Elliott Hughes81baaf22018-02-28 15:22:48 -0800133
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700134 if ((c = *fmt++) != '%')
135 goto literal;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800136
137
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700138again: switch (c = *fmt++) {
139 case '%': /* "%%" is converted to "%". */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800140literal:
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700141 if (c != *bp++)
142 return (NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800143
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700144 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800145
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700146 /*
147 * "Alternative" modifiers. Just set the appropriate flag
148 * and start over again.
149 */
150 case 'E': /* "%E?" alternative conversion modifier. */
151 _LEGAL_ALT(0);
152 alt_format |= _ALT_E;
153 goto again;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800154
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700155 case 'O': /* "%O?" alternative conversion modifier. */
156 _LEGAL_ALT(0);
157 alt_format |= _ALT_O;
158 goto again;
Elliott Hughes81baaf22018-02-28 15:22:48 -0800159
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700160 /*
161 * "Complex" conversion rules, implemented through recursion.
162 */
163 case 'c': /* Date and time, using the locale's format. */
164 _LEGAL_ALT(_ALT_E);
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800165 if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700166 return (NULL);
167 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800168
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700169 case 'D': /* The date as "%m/%d/%y". */
170 _LEGAL_ALT(0);
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800171 if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700172 return (NULL);
173 break;
Elliott Hughes81baaf22018-02-28 15:22:48 -0800174
Elliott Hughesa1fb15b2019-03-26 19:07:40 -0700175 case 'F': /* The date as "%Y-%m-%d". */
176 _LEGAL_ALT(0);
177 if (!(bp = _strptime(bp, "%Y-%m-%d", tm, cr)))
178 return (NULL);
179 continue;
180
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700181 case 'R': /* The time as "%H:%M". */
182 _LEGAL_ALT(0);
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800183 if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700184 return (NULL);
185 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800186
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700187 case 'r': /* The time as "%I:%M:%S %p". */
188 _LEGAL_ALT(0);
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800189 if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700190 return (NULL);
191 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800192
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700193 case 'T': /* The time as "%H:%M:%S". */
194 _LEGAL_ALT(0);
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800195 if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700196 return (NULL);
197 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800198
Elliott Hughesa1fb15b2019-03-26 19:07:40 -0700199 case 'v': /* The date as "%e-%b-%Y". */
200 _LEGAL_ALT(0);
201 if (!(bp = _strptime(bp, "%e-%b-%Y", tm, cr)))
202 return (NULL);
203 break;
204
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700205 case 'X': /* The time, using the locale's format. */
206 _LEGAL_ALT(_ALT_E);
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800207 if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700208 return (NULL);
209 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800210
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700211 case 'x': /* The date, using the locale's format. */
212 _LEGAL_ALT(_ALT_E);
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800213 if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700214 return (NULL);
215 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800216
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700217 /*
218 * "Elementary" conversion rules.
219 */
220 case 'A': /* The day of week, using the locale's form. */
221 case 'a':
222 _LEGAL_ALT(0);
223 for (i = 0; i < 7; i++) {
224 /* Full name. */
225 len = strlen(_ctloc(day[i]));
226 if (strncasecmp(_ctloc(day[i]), (const char*)bp, len) == 0)
227 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800228
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700229 /* Abbreviated name. */
230 len = strlen(_ctloc(abday[i]));
231 if (strncasecmp(_ctloc(abday[i]), (const char*)bp, len) == 0)
232 break;
233 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800234
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700235 /* Nothing matched. */
236 if (i == 7)
237 return (NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800238
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700239 tm->tm_wday = i;
240 bp += len;
241 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800242
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700243 case 'B': /* The month, using the locale's form. */
244 case 'b':
245 case 'h':
246 _LEGAL_ALT(0);
247 for (i = 0; i < 12; i++) {
248 /* Full name. */
249 len = strlen(_ctloc(mon[i]));
250 if (strncasecmp(_ctloc(mon[i]), (const char*)bp, len) == 0)
251 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800252
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700253 /* Abbreviated name. */
254 len = strlen(_ctloc(abmon[i]));
255 if (strncasecmp(_ctloc(abmon[i]), (const char*)bp, len) == 0)
256 break;
257 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800258
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700259 /* Nothing matched. */
260 if (i == 12)
261 return (NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800262
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700263 tm->tm_mon = i;
264 bp += len;
265 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800266
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700267 case 'C': /* The century number. */
268 _LEGAL_ALT(_ALT_E);
269 if (!(_conv_num(&bp, &i, 0, 99)))
270 return (NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800271
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800272 cr->century = i * 100;
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700273 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800274
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700275 case 'd': /* The day of month. */
276 case 'e':
277 _LEGAL_ALT(_ALT_O);
278 if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
279 return (NULL);
280 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800281
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700282 case 'k': /* The hour (24-hour clock representation). */
283 _LEGAL_ALT(0);
284 /* FALLTHROUGH */
285 case 'H':
286 _LEGAL_ALT(_ALT_O);
287 if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
288 return (NULL);
289 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800290
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700291 case 'l': /* The hour (12-hour clock representation). */
292 _LEGAL_ALT(0);
293 /* FALLTHROUGH */
294 case 'I':
295 _LEGAL_ALT(_ALT_O);
296 if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
297 return (NULL);
298 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800299
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700300 case 'j': /* The day of year. */
301 _LEGAL_ALT(0);
302 if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
303 return (NULL);
304 tm->tm_yday--;
305 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800306
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700307 case 'M': /* The minute. */
308 _LEGAL_ALT(_ALT_O);
309 if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
310 return (NULL);
311 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800312
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700313 case 'm': /* The month. */
314 _LEGAL_ALT(_ALT_O);
315 if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
316 return (NULL);
317 tm->tm_mon--;
318 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800319
Elliott Hughesa1fb15b2019-03-26 19:07:40 -0700320 case 'P':
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700321 case 'p': /* The locale's equivalent of AM/PM. */
322 _LEGAL_ALT(0);
323 /* AM? */
324 len = strlen(_ctloc(am_pm[0]));
325 if (strncasecmp(_ctloc(am_pm[0]), (const char*)bp, len) == 0) {
326 if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
327 return (NULL);
328 else if (tm->tm_hour == 12)
329 tm->tm_hour = 0;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800330
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700331 bp += len;
332 break;
333 }
334 /* PM? */
335 len = strlen(_ctloc(am_pm[1]));
336 if (strncasecmp(_ctloc(am_pm[1]), (const char*)bp, len) == 0) {
337 if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
338 return (NULL);
339 else if (tm->tm_hour < 12)
340 tm->tm_hour += 12;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800341
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700342 bp += len;
343 break;
344 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800345
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700346 /* Nothing matched. */
347 return (NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800348
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700349 case 'S': /* The seconds. */
350 _LEGAL_ALT(_ALT_O);
351 if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
352 return (NULL);
353 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800354
Elliott Hughes81baaf22018-02-28 15:22:48 -0800355 case 's':
356 {
357 // Android addition, based on FreeBSD's implementation.
358 int saved_errno = errno;
359 errno = 0;
360 const unsigned char* old_bp = bp;
361 long n = strtol((const char*) bp, (char**) &bp, 10);
362 time_t t = n;
363 if (bp == old_bp || errno == ERANGE || ((long) t) != n) {
364 errno = saved_errno;
365 return NULL;
366 }
367 errno = saved_errno;
368
369 if (localtime_r(&t, tm) == NULL) return NULL;
370 }
371 break;
372
373
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700374 case 'U': /* The week of year, beginning on sunday. */
375 case 'W': /* The week of year, beginning on monday. */
376 _LEGAL_ALT(_ALT_O);
377 /*
378 * XXX This is bogus, as we can not assume any valid
379 * information present in the tm structure at this
380 * point to calculate a real value, so just check the
381 * range for now.
382 */
383 if (!(_conv_num(&bp, &i, 0, 53)))
384 return (NULL);
385 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800386
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700387 case 'w': /* The day of week, beginning on sunday. */
388 _LEGAL_ALT(_ALT_O);
389 if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
390 return (NULL);
391 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800392
Elliott Hughesa1fb15b2019-03-26 19:07:40 -0700393 case 'u': /* The day of week, monday = 1. */
394 _LEGAL_ALT(_ALT_O);
395 if (!(_conv_num(&bp, &i, 1, 7)))
396 return (NULL);
397 tm->tm_wday = i % 7;
398 continue;
399
400 case 'g': /* The year corresponding to the ISO week
401 * number but without the century.
402 */
403 if (!(_conv_num(&bp, &i, 0, 99)))
404 return (NULL);
405 continue;
406
407 case 'G': /* The year corresponding to the ISO week
408 * number with century.
409 */
410 do
411 bp++;
412 while (isdigit(*bp));
413 continue;
414
415 case 'V': /* The ISO 8601:1988 week number as decimal */
416 if (!(_conv_num(&bp, &i, 0, 53)))
417 return (NULL);
418 continue;
419
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700420 case 'Y': /* The year. */
421 _LEGAL_ALT(_ALT_E);
422 if (!(_conv_num(&bp, &i, 0, 9999)))
423 return (NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800424
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800425 cr->relyear = -1;
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700426 tm->tm_year = i - TM_YEAR_BASE;
427 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800428
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700429 case 'y': /* The year within the century (2 digits). */
430 _LEGAL_ALT(_ALT_E | _ALT_O);
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800431 if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700432 return (NULL);
433 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800434
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700435 /*
436 * Miscellaneous conversions.
437 */
438 case 'n': /* Any kind of white-space. */
439 case 't':
440 _LEGAL_ALT(0);
441 while (isspace(*bp))
442 bp++;
443 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800444
445
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700446 default: /* Unknown/unsupported conversion. */
447 return (NULL);
448 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800449
450
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700451 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800452
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700453 /*
454 * We need to evaluate the two digit year spec (%y)
455 * last as we can get a century spec (%C) at any time.
456 */
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800457 if (cr->relyear != -1) {
458 if (cr->century == TM_YEAR_BASE) {
459 if (cr->relyear <= 68)
460 tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700461 else
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800462 tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700463 } else {
Glenn Kastenb138e4f2011-01-09 10:33:23 -0800464 tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700465 }
466 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800467
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700468 return (unsigned char*)bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800469}
470
471
472static int
473_conv_num(const unsigned char **buf, int *dest, int llim, int ulim)
474{
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700475 int result = 0;
476 int rulim = ulim;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800477
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700478 if (**buf < '0' || **buf > '9')
479 return (0);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800480
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700481 /* we use rulim to break out of the loop when we run out of digits */
482 do {
483 result *= 10;
484 result += *(*buf)++ - '0';
485 rulim /= 10;
486 } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800487
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700488 if (result < llim || result > ulim)
489 return (0);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800490
The Android Open Source Projectedbe7fc2009-03-18 22:20:24 -0700491 *dest = result;
492 return (1);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800493}
Elliott Hughes3376c232018-02-13 23:14:12 -0800494
495char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t l) {
496 return strptime(buf, fmt, tm);
497}