1 /*
2 * Copyright 2011, Nexenta Systems, Inc. All rights reserved.
3 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * official policies, either expressed or implied, of Powerdog Industries.
32 */
33
34 #include "lint.h"
35 #include <time.h>
36 #include <ctype.h>
37 #include <errno.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <pthread.h>
41 #include <alloca.h>
42 #include "timelocal.h"
43
44 #define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
45
46 #define F_GMT (1 << 0)
47 #define F_ZERO (1 << 1)
48 #define F_RECURSE (1 << 2)
49
50 static char *
51 __strptime(const char *buf, const char *fmt, struct tm *tm, int *flagsp)
52 {
53 char c;
54 const char *ptr;
55 int i, len, recurse = 0;
56 int Ealternative, Oalternative;
57 struct lc_time_T *tptr = __get_current_time_locale();
58
59 if (*flagsp & F_RECURSE)
60 recurse = 1;
61 *flagsp |= F_RECURSE;
62
63 if (*flagsp & F_ZERO)
64 (void) memset(tm, 0, sizeof (*tm));
65 *flagsp &= ~F_ZERO;
66
67 ptr = fmt;
68 while (*ptr != 0) {
69 if (*buf == 0)
70 break;
71
72 c = *ptr++;
73
74 if (c != '%') {
75 if (isspace(c))
76 while (isspace(*buf))
77 buf++;
78 else if (c != *buf++)
79 return (NULL);
80 continue;
81 }
82
83 Ealternative = 0;
84 Oalternative = 0;
85 label:
86 c = *ptr++;
87 switch (c) {
88 case 0:
89 case '%':
90 if (*buf++ != '%')
91 return (NULL);
92 break;
93
94 case '+':
95 buf = __strptime(buf, tptr->date_fmt, tm, flagsp);
96 if (buf == NULL)
97 return (NULL);
98 break;
99
100 case 'C':
101 if (!isdigit(*buf))
102 return (NULL);
103
104 /* XXX This will break for 3-digit centuries. */
105 len = 2;
106 for (i = 0; len && isdigit(*buf); buf++) {
107 i *= 10;
108 i += *buf - '0';
109 len--;
110 }
111 if (i < 19)
112 return (NULL);
113
114 tm->tm_year = i * 100 - 1900;
115 break;
116
117 case 'c':
118 buf = __strptime(buf, tptr->c_fmt, tm, flagsp);
119 if (buf == NULL)
120 return (NULL);
121 break;
122
123 case 'D':
124 buf = __strptime(buf, "%m/%d/%y", tm, flagsp);
125 if (buf == NULL)
126 return (NULL);
127 break;
128
129 case 'E':
130 if (Ealternative || Oalternative)
131 break;
132 Ealternative++;
133 goto label;
134
135 case 'O':
136 if (Ealternative || Oalternative)
137 break;
138 Oalternative++;
139 goto label;
140
141 case 'F':
142 buf = __strptime(buf, "%Y-%m-%d", tm, flagsp);
143 if (buf == NULL)
144 return (NULL);
145 break;
146
147 case 'R':
148 buf = __strptime(buf, "%H:%M", tm, flagsp);
149 if (buf == NULL)
150 return (NULL);
151 break;
152
153 case 'r':
154 buf = __strptime(buf, tptr->ampm_fmt, tm, flagsp);
155 if (buf == NULL)
156 return (NULL);
157 break;
158
159 case 'T':
160 buf = __strptime(buf, "%H:%M:%S", tm, flagsp);
161 if (buf == NULL)
162 return (NULL);
163 break;
164
165 case 'X':
166 buf = __strptime(buf, tptr->X_fmt, tm, flagsp);
167 if (buf == NULL)
168 return (NULL);
169 break;
170
171 case 'x':
172 buf = __strptime(buf, tptr->x_fmt, tm, flagsp);
173 if (buf == NULL)
174 return (NULL);
175 break;
176
177 case 'j':
178 if (!isdigit(*buf))
179 return (NULL);
180
181 len = 3;
182 for (i = 0; len && isdigit(*buf); buf++) {
183 i *= 10;
184 i += *buf - '0';
185 len--;
186 }
187 if (i < 1 || i > 366)
188 return (NULL);
189
190 tm->tm_yday = i - 1;
191 break;
192
518
519 tm->tm_hour -= sign * (i / 100);
520 tm->tm_min -= sign * (i % 100);
521 *flagsp |= F_GMT;
522 }
523 break;
524 }
525 }
526
527 if (!recurse) {
528 if (buf && (*flagsp & F_GMT)) {
529 time_t t = timegm(tm);
530 (void) localtime_r(&t, tm);
531 }
532 }
533
534 return ((char *)buf);
535 }
536
537 char *
538 strptime(const char *buf, const char *fmt, struct tm *tm)
539 {
540 int flags = F_ZERO;
541
542 return (__strptime(buf, fmt, tm, &flags));
543 }
544
545 /*
546 * This is used by Solaris, and is a variant that does not clear the
547 * incoming tm. It is triggered by -D_STRPTIME_DONTZERO.
548 */
549 char *
550 __strptime_dontzero(const char *buf, const char *fmt, struct tm *tm)
551 {
552 int flags = 0;
553
554 return (__strptime(buf, fmt, tm, &flags));
555 }
|
1 /*
2 * Copyright 2011, Nexenta Systems, Inc. All rights reserved.
3 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
4 *
5 * Copyright (c) 2011 The FreeBSD Foundation
6 * All rights reserved.
7 * Portions of this software were developed by David Chisnall
8 * under sponsorship from the FreeBSD Foundation.
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 *
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 *
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer
19 * in the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
23 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36 * official policies, either expressed or implied, of Powerdog Industries.
37 */
38
39 #include "lint.h"
40 #include <time.h>
41 #include <ctype.h>
42 #include <errno.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <pthread.h>
46 #include <alloca.h>
47 #include "timelocal.h"
48
49 #define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
50
51 #define F_GMT (1 << 0)
52 #define F_ZERO (1 << 1)
53 #define F_RECURSE (1 << 2)
54
55 static char *
56 __strptime(const char *buf, const char *fmt, struct tm *tm, int *flagsp,
57 int *GMTp, locale_t locale)
58 {
59 char c;
60 const char *ptr;
61 int i, len, recurse = 0;
62 int Ealternative, Oalternative;
63 struct lc_time_T *tptr = __get_current_time_locale(locale);
64
65 if (*flagsp & F_RECURSE)
66 recurse = 1;
67 *flagsp |= F_RECURSE;
68
69 if (*flagsp & F_ZERO)
70 (void) memset(tm, 0, sizeof (*tm));
71 *flagsp &= ~F_ZERO;
72
73 ptr = fmt;
74 while (*ptr != 0) {
75 if (*buf == 0)
76 break;
77
78 c = *ptr++;
79
80 if (c != '%') {
81 if (isspace(c))
82 while (isspace(*buf))
83 buf++;
84 else if (c != *buf++)
85 return (NULL);
86 continue;
87 }
88
89 Ealternative = 0;
90 Oalternative = 0;
91 label:
92 c = *ptr++;
93 switch (c) {
94 case 0:
95 case '%':
96 if (*buf++ != '%')
97 return (NULL);
98 break;
99
100 case '+':
101 buf = __strptime(buf, tptr->date_fmt, tm, flagsp,
102 GMTp, locale);
103 if (buf == NULL)
104 return (NULL);
105 break;
106
107 case 'C':
108 if (!isdigit(*buf))
109 return (NULL);
110
111 /* XXX This will break for 3-digit centuries. */
112 len = 2;
113 for (i = 0; len && isdigit(*buf); buf++) {
114 i *= 10;
115 i += *buf - '0';
116 len--;
117 }
118 if (i < 19)
119 return (NULL);
120
121 tm->tm_year = i * 100 - 1900;
122 break;
123
124 case 'c':
125 buf = __strptime(buf, tptr->c_fmt, tm, flagsp,
126 GMTp, locale);
127 if (buf == NULL)
128 return (NULL);
129 break;
130
131 case 'D':
132 buf = __strptime(buf, "%m/%d/%y", tm, flagsp,
133 GMTp, locale);
134 if (buf == NULL)
135 return (NULL);
136 break;
137
138 case 'E':
139 if (Ealternative || Oalternative)
140 break;
141 Ealternative++;
142 goto label;
143
144 case 'O':
145 if (Ealternative || Oalternative)
146 break;
147 Oalternative++;
148 goto label;
149
150 case 'F':
151 buf = __strptime(buf, "%Y-%m-%d", tm, flagsp,
152 GMTp, locale);
153 if (buf == NULL)
154 return (NULL);
155 break;
156
157 case 'R':
158 buf = __strptime(buf, "%H:%M", tm, flagsp,
159 GMTp, locale);
160 if (buf == NULL)
161 return (NULL);
162 break;
163
164 case 'r':
165 buf = __strptime(buf, tptr->ampm_fmt, tm, flagsp,
166 GMTp, locale);
167 if (buf == NULL)
168 return (NULL);
169 break;
170
171 case 'T':
172 buf = __strptime(buf, "%H:%M:%S", tm, flagsp,
173 GMTp, locale);
174 if (buf == NULL)
175 return (NULL);
176 break;
177
178 case 'X':
179 buf = __strptime(buf, tptr->X_fmt, tm, flagsp,
180 GMTp, locale);
181 if (buf == NULL)
182 return (NULL);
183 break;
184
185 case 'x':
186 buf = __strptime(buf, tptr->x_fmt, tm, flagsp,
187 GMTp, locale);
188 if (buf == NULL)
189 return (NULL);
190 break;
191
192 case 'j':
193 if (!isdigit(*buf))
194 return (NULL);
195
196 len = 3;
197 for (i = 0; len && isdigit(*buf); buf++) {
198 i *= 10;
199 i += *buf - '0';
200 len--;
201 }
202 if (i < 1 || i > 366)
203 return (NULL);
204
205 tm->tm_yday = i - 1;
206 break;
207
533
534 tm->tm_hour -= sign * (i / 100);
535 tm->tm_min -= sign * (i % 100);
536 *flagsp |= F_GMT;
537 }
538 break;
539 }
540 }
541
542 if (!recurse) {
543 if (buf && (*flagsp & F_GMT)) {
544 time_t t = timegm(tm);
545 (void) localtime_r(&t, tm);
546 }
547 }
548
549 return ((char *)buf);
550 }
551
552 char *
553 strptime_l(const char * __restrict buf, const char * __restrict fmt,
554 struct tm * __restrict tm, locale_t loc)
555 {
556 char *ret;
557 int gmt;
558 int flags = F_ZERO;
559 FIX_LOCALE(loc);
560
561 gmt = 0;
562 ret = __strptime(buf, fmt, tm, &flags, &gmt, loc);
563 if (ret && gmt) {
564 time_t t = timegm(tm);
565 localtime_r(&t, tm);
566 }
567
568 return (ret);
569 }
570
571 char *
572 strptime(const char *buf, const char *fmt, struct tm *tm)
573 {
574 int flags = F_ZERO;
575
576 return (strptime_l(buf, fmt, tm, __get_locale()));
577 // XXX return (__strptime(buf, fmt, tm, &flags));
578 }
579
580 /*
581 * This is used by Solaris, and is a variant that does not clear the
582 * incoming tm. It is triggered by -D_STRPTIME_DONTZERO.
583 */
584 char *
585 __strptime_dontzero(const char *buf, const char *fmt, struct tm *tm)
586 {
587 int flags = 0;
588 int gmt = 0;
589
590 return (__strptime(buf, fmt, tm, &flags, &gmt, __get_locale()));
591 /* XXX */
592 }
|