View | Details | Raw Unified | Return to bug 137307 | Differences between
and this patch

Collapse All | Expand All

(-)strptime.c (-7 / +119 lines)
Lines 55-64 Link Here
55
#include "un-namespace.h"
55
#include "un-namespace.h"
56
#include "libc_private.h"
56
#include "libc_private.h"
57
#include "timelocal.h"
57
#include "timelocal.h"
58
58
#include "tzfile.h"
59
#include <stdio.h>
59
static char * _strptime(const char *, const char *, struct tm *, int *, locale_t);
60
static char * _strptime(const char *, const char *, struct tm *, int *, locale_t);
60
61
61
#define	asizeof(a)	(sizeof (a) / sizeof ((a)[0]))
62
#define	asizeof(a)	(sizeof(a) / sizeof((a)[0]))
63
64
#define	FLAG_NONE	(1 << 0)
65
#define	FLAG_YEAR	(1 << 1)
66
#define	FLAG_MONTH	(1 << 2)
67
#define	FLAG_YDAY	(1 << 3)
68
#define	FLAG_MDAY	(1 << 4)
69
#define	FLAG_WDAY	(1 << 5)
70
71
/*
72
 * Calculate the week day of the first day of a year. Valid for
73
 * the Gregorian calendar, which began Sept 14, 1752 in the UK
74
 * and its colonies. Ref:
75
 * http://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week
76
 */
77
78
static int
79
first_wday_of(int year)
80
{
81
	return (((2 * (3 - (year / 100) % 4)) + (year % 100) +
82
		((year % 100) / 4) + (isleap(year) ? 6 : 0) + 1) % 7);
83
}
62
84
63
static char *
85
static char *
64
_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp,
86
_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp,
Lines 66-74 Link Here
66
{
88
{
67
	char	c;
89
	char	c;
68
	const char *ptr;
90
	const char *ptr;
91
	int	day_offset = -1, wday_offset;
92
	int week_offset;
69
	int	i, len;
93
	int	i, len;
94
	int flags;
70
	int Ealternative, Oalternative;
95
	int Ealternative, Oalternative;
71
	struct lc_time_T *tptr = __get_current_time_locale(locale);
96
	const struct lc_time_T *tptr = __get_current_time_locale(locale);
97
	static int start_of_month[2][13] = {
98
		{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
99
		{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
100
	};
101
102
	flags = FLAG_NONE;
72
103
73
	ptr = fmt;
104
	ptr = fmt;
74
	while (*ptr != 0) {
105
	while (*ptr != 0) {
Lines 102-107 Link Here
102
			buf = _strptime(buf, tptr->date_fmt, tm, GMTp, locale);
133
			buf = _strptime(buf, tptr->date_fmt, tm, GMTp, locale);
103
			if (buf == NULL)
134
			if (buf == NULL)
104
				return (NULL);
135
				return (NULL);
136
			flags |= FLAG_WDAY | FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;
105
			break;
137
			break;
106
138
107
		case 'C':
139
		case 'C':
Lines 119-137 Link Here
119
			if (i < 19)
151
			if (i < 19)
120
				return (NULL);
152
				return (NULL);
121
153
122
			tm->tm_year = i * 100 - 1900;
154
			tm->tm_year = i * 100 - TM_YEAR_BASE;
155
			flags |= FLAG_YEAR;
156
123
			break;
157
			break;
124
158
125
		case 'c':
159
		case 'c':
126
			buf = _strptime(buf, tptr->c_fmt, tm, GMTp, locale);
160
			buf = _strptime(buf, tptr->c_fmt, tm, GMTp, locale);
127
			if (buf == NULL)
161
			if (buf == NULL)
128
				return (NULL);
162
				return (NULL);
163
			flags |= FLAG_WDAY | FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;
129
			break;
164
			break;
130
165
131
		case 'D':
166
		case 'D':
132
			buf = _strptime(buf, "%m/%d/%y", tm, GMTp, locale);
167
			buf = _strptime(buf, "%m/%d/%y", tm, GMTp, locale);
133
			if (buf == NULL)
168
			if (buf == NULL)
134
				return (NULL);
169
				return (NULL);
170
			flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;
135
			break;
171
			break;
136
172
137
		case 'E':
173
		case 'E':
Lines 150-155 Link Here
150
			buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, locale);
186
			buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, locale);
151
			if (buf == NULL)
187
			if (buf == NULL)
152
				return (NULL);
188
				return (NULL);
189
			flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;
153
			break;
190
			break;
154
191
155
		case 'R':
192
		case 'R':
Lines 180-185 Link Here
180
			buf = _strptime(buf, tptr->x_fmt, tm, GMTp, locale);
217
			buf = _strptime(buf, tptr->x_fmt, tm, GMTp, locale);
181
			if (buf == NULL)
218
			if (buf == NULL)
182
				return (NULL);
219
				return (NULL);
220
			flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;
183
			break;
221
			break;
184
222
185
		case 'j':
223
		case 'j':
Lines 197-202 Link Here
197
				return (NULL);
235
				return (NULL);
198
236
199
			tm->tm_yday = i - 1;
237
			tm->tm_yday = i - 1;
238
			flags |= FLAG_YDAY;
239
200
			break;
240
			break;
201
241
202
		case 'M':
242
		case 'M':
Lines 303-309 Link Here
303
				return (NULL);
343
				return (NULL);
304
344
305
			tm->tm_wday = i;
345
			tm->tm_wday = i;
306
			buf += len;
346
			flags |= FLAG_WDAY;
307
			break;
347
			break;
308
348
309
		case 'U':
349
		case 'U':
Lines 327-332 Link Here
327
			if (i > 53)
367
			if (i > 53)
328
				return (NULL);
368
				return (NULL);
329
369
370
			if (c == 'U')
371
				day_offset = TM_SUNDAY;
372
			else
373
				day_offset = TM_MONDAY;
374
375
376
			week_offset = i;
377
330
			break;
378
			break;
331
379
332
		case 'w':
380
		case 'w':
Lines 338-343 Link Here
338
				return (NULL);
386
				return (NULL);
339
387
340
			tm->tm_wday = i;
388
			tm->tm_wday = i;
389
			flags |= FLAG_WDAY;
341
390
342
			break;
391
			break;
343
392
Lines 374-379 Link Here
374
				return (NULL);
423
				return (NULL);
375
424
376
			tm->tm_mday = i;
425
			tm->tm_mday = i;
426
			flags |= FLAG_MDAY;
377
427
378
			break;
428
			break;
379
429
Lines 413-418 Link Here
413
463
414
			tm->tm_mon = i;
464
			tm->tm_mon = i;
415
			buf += len;
465
			buf += len;
466
			flags |= FLAG_MONTH;
467
416
			break;
468
			break;
417
469
418
		case 'm':
470
		case 'm':
Lines 430-435 Link Here
430
				return (NULL);
482
				return (NULL);
431
483
432
			tm->tm_mon = i - 1;
484
			tm->tm_mon = i - 1;
485
			flags |= FLAG_MONTH;
433
486
434
			break;
487
			break;
435
488
Lines 471-483 Link Here
471
				len--;
524
				len--;
472
			}
525
			}
473
			if (c == 'Y')
526
			if (c == 'Y')
474
				i -= 1900;
527
				i -= TM_YEAR_BASE;
475
			if (c == 'y' && i < 69)
528
			if (c == 'y' && i < 69)
476
				i += 100;
529
				i += 100;
477
			if (i < 0)
530
			if (i < 0)
478
				return (NULL);
531
				return (NULL);
479
532
480
			tm->tm_year = i;
533
			tm->tm_year = i;
534
			flags |= FLAG_YEAR;
481
535
482
			break;
536
			break;
483
537
Lines 543-552 Link Here
543
			break;
597
			break;
544
		}
598
		}
545
	}
599
	}
600
601
	if (!(flags & FLAG_YDAY) && (flags & FLAG_YEAR)) {
602
		if ((flags & (FLAG_MONTH | FLAG_MDAY)) ==
603
		    (FLAG_MONTH | FLAG_MDAY)) {
604
			tm->tm_yday = start_of_month[isleap(tm->tm_year +
605
			    TM_YEAR_BASE)][tm->tm_mon] + (tm->tm_mday - 1);
606
			flags |= FLAG_YDAY;
607
		} else if (day_offset != -1) {
608
			/* Set the date to the first Sunday (or Monday)
609
			 * of the specified week of the year.
610
			 */
611
			if (!(flags & FLAG_WDAY)) {
612
				tm->tm_wday = day_offset;
613
				flags |= FLAG_WDAY;
614
			}
615
			tm->tm_yday = (7 -
616
			    first_wday_of(tm->tm_year + TM_YEAR_BASE) +
617
			    day_offset) % 7 + (week_offset - 1) * 7 +
618
			    tm->tm_wday - day_offset;
619
			flags |= FLAG_YDAY;
620
		}
621
	}
622
623
	if ((flags & (FLAG_YEAR | FLAG_YDAY)) == (FLAG_YEAR | FLAG_YDAY)) {
624
		if (!(flags & FLAG_MONTH)) {
625
			i = 0;
626
			while (tm->tm_yday >=
627
			    start_of_month[isleap(tm->tm_year +
628
			    TM_YEAR_BASE)][i])
629
				i++;
630
			if (i > 12) {
631
				i = 1;
632
				tm->tm_yday -=
633
				    start_of_month[isleap(tm->tm_year +
634
				    TM_YEAR_BASE)][12];
635
				tm->tm_year++;
636
			}
637
			tm->tm_mon = i - 1;
638
			flags |= FLAG_MONTH;
639
		}
640
		if (!(flags & FLAG_MDAY)) {
641
			tm->tm_mday = tm->tm_yday -
642
			    start_of_month[isleap(tm->tm_year + TM_YEAR_BASE)]
643
			    [tm->tm_mon] + 1;
644
			flags |= FLAG_MDAY;
645
		}
646
		if (!(flags & FLAG_WDAY)) {
647
			i = 0;
648
			wday_offset = first_wday_of(tm->tm_year);
649
			while (i++ <= tm->tm_yday) {
650
				if (wday_offset++ >= 6)
651
					wday_offset = 0;
652
			}
653
			tm->tm_wday = wday_offset;
654
			flags |= FLAG_WDAY;
655
		}
656
	}
657
546
	return ((char *)buf);
658
	return ((char *)buf);
547
}
659
}
548
660
549
550
char *
661
char *
551
strptime_l(const char * __restrict buf, const char * __restrict fmt,
662
strptime_l(const char * __restrict buf, const char * __restrict fmt,
552
    struct tm * __restrict tm, locale_t loc)
663
    struct tm * __restrict tm, locale_t loc)
Lines 564-569 Link Here
564
675
565
	return (ret);
676
	return (ret);
566
}
677
}
678
567
char *
679
char *
568
strptime(const char * __restrict buf, const char * __restrict fmt,
680
strptime(const char * __restrict buf, const char * __restrict fmt,
569
    struct tm * __restrict tm)
681
    struct tm * __restrict tm)

Return to bug 137307