strptime.c revision 1.2 1 /* $NetBSD: strptime.c,v 1.2 1997/05/06 13:06:48 kleink Exp $ */
2
3 /*
4 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * 3. All advertising materials mentioning features or use of this
16 * software must display the following acknowledgement:
17 * This product includes software developed by Powerdog Industries.
18 * 4. The name of Powerdog Industries may not be used to endorse or
19 * promote products derived from this software without specific prior
20 * written permission.
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,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #ifndef lint
36 #if 0
37 static char copyright[] =
38 "@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved.";
39 static char sccsid[] = "@(#)strptime.c 0.1 (Powerdog) 94/03/27";
40 #else
41 static char rcsid[] = "$NetBSD: strptime.c,v 1.2 1997/05/06 13:06:48 kleink Exp $";
42 #endif
43 #endif /* not lint */
44
45 #include <sys/localedef.h>
46 #include <locale.h>
47 #include <time.h>
48 #include <ctype.h>
49 #include <string.h>
50
51 char *
52 strptime(buf, fmt, tm)
53 const char *buf, *fmt;
54 struct tm *tm;
55 {
56 const char *ptr;
57 char c;
58 int i, len;
59
60 ptr = fmt;
61 while (*ptr != 0) {
62 if (*buf == 0)
63 break;
64
65 c = *ptr++;
66
67 if (c != '%') {
68 if (isspace(c))
69 while (*buf != 0 && isspace(*buf))
70 buf++;
71 else if (c != *buf++)
72 return (NULL);
73 continue;
74 }
75
76 c = *ptr++;
77 switch (c) {
78 case 0:
79 case '%':
80 if (*buf++ != '%')
81 return (NULL);
82 break;
83
84 case 'c':
85 buf = strptime(buf, _CurrentTimeLocale->d_t_fmt, tm);
86 if (buf == 0)
87 return (NULL);
88 break;
89
90 case 'D':
91 buf = strptime(buf, "%m/%d/%y", tm);
92 if (buf == 0)
93 return (NULL);
94 break;
95
96 case 'R':
97 buf = strptime(buf, "%H:%M", tm);
98 if (buf == 0)
99 return (NULL);
100 break;
101
102 case 'r':
103 buf = strptime(buf, _CurrentTimeLocale->t_fmt_ampm,tm);
104 if (buf == 0)
105 return (NULL);
106 break;
107
108 case 'T':
109 buf = strptime(buf, "%H:%M:%S", tm);
110 if (buf == 0)
111 return (NULL);
112 break;
113
114 case 'X':
115 buf = strptime(buf, _CurrentTimeLocale->t_fmt, tm);
116 if (buf == 0)
117 return (NULL);
118 break;
119
120 case 'x':
121 buf = strptime(buf, _CurrentTimeLocale->d_fmt, tm);
122 if (buf == 0)
123 return (NULL);
124 break;
125
126 case 'j':
127 if (!isdigit(*buf))
128 return (NULL);
129
130 for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
131 i *= 10;
132 i += *buf - '0';
133 }
134 if (i > 366)
135 return (NULL);
136
137 tm->tm_yday = i;
138 break;
139
140 case 'M':
141 case 'S':
142 if (*buf == 0 || isspace(*buf))
143 break;
144
145 if (!isdigit(*buf))
146 return (NULL);
147
148 for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
149 i *= 10;
150 i += *buf - '0';
151 }
152 if (i > 59)
153 return (NULL);
154
155 if (c == 'M')
156 tm->tm_min = i;
157 else
158 tm->tm_sec = i;
159
160 if (*buf != 0 && isspace(*buf))
161 while (*ptr != 0 && !isspace(*ptr))
162 ptr++;
163 break;
164
165 case 'H':
166 case 'I':
167 case 'k':
168 case 'l':
169 if (!isdigit(*buf))
170 return (NULL);
171
172 for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
173 i *= 10;
174 i += *buf - '0';
175 }
176 if (c == 'H' || c == 'k') {
177 if (i > 23)
178 return (NULL);
179 } else if (i > 11)
180 return (NULL);
181
182 tm->tm_hour = i;
183
184 if (*buf != 0 && isspace(*buf))
185 while (*ptr != 0 && !isspace(*ptr))
186 ptr++;
187 break;
188
189 case 'p':
190 len = strlen(_CurrentTimeLocale->am_pm[0]);
191 if (strncasecmp(buf, _CurrentTimeLocale->am_pm[0],
192 len) == 0) {
193 if (tm->tm_hour > 12)
194 return (NULL);
195 if (tm->tm_hour == 12)
196 tm->tm_hour = 0;
197 buf += len;
198 break;
199 }
200
201 len = strlen(_CurrentTimeLocale->am_pm[1]);
202 if (strncasecmp(buf, _CurrentTimeLocale->am_pm[1],
203 len) == 0) {
204 if (tm->tm_hour > 12)
205 return (NULL);
206 if (tm->tm_hour != 12)
207 tm->tm_hour += 12;
208 buf += len;
209 break;
210 }
211
212 return (NULL);
213
214 case 'A':
215 case 'a':
216 for (i = 0; i < 7; i++) {
217 len = strlen(_CurrentTimeLocale->day[i]);
218 if (strncasecmp(buf,
219 _CurrentTimeLocale->day[i],
220 len) == 0)
221 break;
222
223 len = strlen(_CurrentTimeLocale->abday[i]);
224 if (strncasecmp(buf,
225 _CurrentTimeLocale->abday[i],
226 len) == 0)
227 break;
228 }
229 if (i == 7)
230 return (NULL);
231
232 tm->tm_wday = i;
233 buf += len;
234 break;
235
236 case 'd':
237 case 'e':
238 if (!isdigit(*buf))
239 return (NULL);
240
241 for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
242 i *= 10;
243 i += *buf - '0';
244 }
245 if (i > 31)
246 return (NULL);
247
248 tm->tm_mday = i;
249
250 if (*buf != 0 && isspace(*buf))
251 while (*ptr != 0 && !isspace(*ptr))
252 ptr++;
253 break;
254
255 case 'B':
256 case 'b':
257 case 'h':
258 for (i = 0; i < 12; i++) {
259 len = strlen(_CurrentTimeLocale->mon[i]);
260 if (strncasecmp(buf,
261 _CurrentTimeLocale->mon[i],
262 len) == 0)
263 break;
264
265 len = strlen(_CurrentTimeLocale->abmon[i]);
266 if (strncasecmp(buf,
267 _CurrentTimeLocale->abmon[i],
268 len) == 0)
269 break;
270 }
271 if (i == 12)
272 return (NULL);
273
274 tm->tm_mon = i;
275 buf += len;
276 break;
277
278 case 'm':
279 if (!isdigit(*buf))
280 return (NULL);
281
282 for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
283 i *= 10;
284 i += *buf - '0';
285 }
286 if (i < 1 || i > 12)
287 return (NULL);
288
289 tm->tm_mon = i - 1;
290
291 if (*buf != 0 && isspace(*buf))
292 while (*ptr != 0 && !isspace(*ptr))
293 ptr++;
294 break;
295
296 case 'Y':
297 case 'y':
298 if (*buf == 0 || isspace(*buf))
299 break;
300
301 if (!isdigit(*buf))
302 return (NULL);
303
304 for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
305 i *= 10;
306 i += *buf - '0';
307 }
308 if (c == 'Y')
309 i -= 1900;
310 if (i < 0)
311 return (NULL);
312
313 tm->tm_year = i;
314
315 if (*buf != 0 && isspace(*buf))
316 while (*ptr != 0 && !isspace(*ptr))
317 ptr++;
318 break;
319 }
320 }
321
322 return ((char *)buf);
323 }
324