xref: /netbsd-src/lib/libc/time/strptime.c (revision d0fed6c87ddc40a8bffa6f99e7433ddfc864dd83)
1 /*	$NetBSD: strptime.c,v 1.1 1997/04/23 01:18:06 mrg 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.1 1997/04/23 01:18:06 mrg 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(const char *buf, const char *fmt, struct tm *tm)
53 {
54 	const char *ptr;
55         char    c;
56 	int     i, len;
57 
58         ptr = fmt;
59         while (*ptr != 0) {
60                 if (*buf == 0)
61                         break;
62 
63                 c = *ptr++;
64 
65                 if (c != '%') {
66                         if (isspace(c))
67                                 while (*buf != 0 && isspace(*buf))
68                                         buf++;
69                         else if (c != *buf++)
70                                 return 0;
71                         continue;
72                 }
73 
74                 c = *ptr++;
75                 switch (c) {
76                 case 0:
77                 case '%':
78                         if (*buf++ != '%')
79                                 return 0;
80                         break;
81 
82                 case 'c':
83                         buf = strptime(buf, _CurrentTimeLocale->d_t_fmt, tm);
84                         if (buf == 0)
85                                 return 0;
86                         break;
87 
88                 case 'D':
89                         buf = strptime(buf, "%m/%d/%y", tm);
90                         if (buf == 0)
91                                 return 0;
92                         break;
93 
94                 case 'R':
95                         buf = strptime(buf, "%H:%M", tm);
96                         if (buf == 0)
97                                 return 0;
98                         break;
99 
100                 case 'r':
101                         buf = strptime(buf, _CurrentTimeLocale->t_fmt_ampm,tm);
102                         if (buf == 0)
103                                 return 0;
104                         break;
105 
106                 case 'T':
107                         buf = strptime(buf, "%H:%M:%S", tm);
108                         if (buf == 0)
109                                 return 0;
110                         break;
111 
112                 case 'X':
113                         buf = strptime(buf, _CurrentTimeLocale->t_fmt, tm);
114                         if (buf == 0)
115                                 return 0;
116                         break;
117 
118                 case 'x':
119                         buf = strptime(buf, _CurrentTimeLocale->d_fmt, tm);
120                         if (buf == 0)
121                                 return 0;
122                         break;
123 
124                 case 'j':
125                         if (!isdigit(*buf))
126                                 return 0;
127 
128                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
129                                 i *= 10;
130                                 i += *buf - '0';
131                         }
132                         if (i > 366)
133                                 return 0;
134 
135                         tm->tm_yday = i;
136                         break;
137 
138                 case 'M':
139                 case 'S':
140                         if (*buf == 0 || isspace(*buf))
141                                 break;
142 
143                         if (!isdigit(*buf))
144                                 return 0;
145 
146                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
147                                 i *= 10;
148                                 i += *buf - '0';
149                         }
150                         if (i > 59)
151                                 return 0;
152 
153                         if (c == 'M')
154                                 tm->tm_min = i;
155                         else
156                                 tm->tm_sec = i;
157 
158                         if (*buf != 0 && isspace(*buf))
159                                 while (*ptr != 0 && !isspace(*ptr))
160                                         ptr++;
161                         break;
162 
163                 case 'H':
164                 case 'I':
165                 case 'k':
166                 case 'l':
167                         if (!isdigit(*buf))
168                                 return 0;
169 
170                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
171                                 i *= 10;
172                                 i += *buf - '0';
173                         }
174                         if (c == 'H' || c == 'k') {
175                                 if (i > 23)
176                                         return 0;
177                         } else if (i > 11)
178                                 return 0;
179 
180                         tm->tm_hour = i;
181 
182                         if (*buf != 0 && isspace(*buf))
183                                 while (*ptr != 0 && !isspace(*ptr))
184                                         ptr++;
185                         break;
186 
187                 case 'p':
188                         len = strlen(_CurrentTimeLocale->am_pm[0]);
189                         if (strncasecmp(buf, _CurrentTimeLocale->am_pm[0],
190 					len) == 0) {
191                                 if (tm->tm_hour > 12)
192                                         return 0;
193                                 if (tm->tm_hour == 12)
194                                         tm->tm_hour = 0;
195                                 buf += len;
196                                 break;
197                         }
198 
199                         len = strlen(_CurrentTimeLocale->am_pm[1]);
200                         if (strncasecmp(buf, _CurrentTimeLocale->am_pm[1],
201 					len) == 0) {
202                                 if (tm->tm_hour > 12)
203                                         return 0;
204                                 if (tm->tm_hour != 12)
205                                         tm->tm_hour += 12;
206                                 buf += len;
207                                 break;
208                         }
209 
210                         return 0;
211 
212                 case 'A':
213                 case 'a':
214                         for (i = 0; i < 7; i++) {
215                                 len = strlen(_CurrentTimeLocale->day[i]);
216                                 if (strncasecmp(buf,
217 						_CurrentTimeLocale->day[i],
218 						len) == 0)
219 					break;
220 
221                                 len = strlen(_CurrentTimeLocale->abday[i]);
222                                 if (strncasecmp(buf,
223 						_CurrentTimeLocale->abday[i],
224 						len) == 0)
225 					break;
226                         }
227                         if (i == 7)
228                                 return 0;
229 
230                         tm->tm_wday = i;
231                         buf += len;
232                         break;
233 
234                 case 'd':
235                 case 'e':
236                         if (!isdigit(*buf))
237                                 return 0;
238 
239                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
240                                 i *= 10;
241                                 i += *buf - '0';
242                         }
243                         if (i > 31)
244                                 return 0;
245 
246                         tm->tm_mday = i;
247 
248                         if (*buf != 0 && isspace(*buf))
249                                 while (*ptr != 0 && !isspace(*ptr))
250                                         ptr++;
251                         break;
252 
253                 case 'B':
254                 case 'b':
255                 case 'h':
256                         for (i = 0; i < 12; i++) {
257 				len = strlen(_CurrentTimeLocale->mon[i]);
258                                 if (strncasecmp(buf,
259 						_CurrentTimeLocale->mon[i],
260                                                 len) == 0)
261                                         break;
262 
263 				len = strlen(_CurrentTimeLocale->abmon[i]);
264                                 if (strncasecmp(buf,
265 						_CurrentTimeLocale->abmon[i],
266                                                 len) == 0)
267                                         break;
268                         }
269                         if (i == 12)
270                                 return 0;
271 
272                         tm->tm_mon = i;
273                         buf += len;
274                         break;
275 
276                 case 'm':
277                         if (!isdigit(*buf))
278                                 return 0;
279 
280                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
281                                 i *= 10;
282                                 i += *buf - '0';
283                         }
284                         if (i < 1 || i > 12)
285                                 return 0;
286 
287                         tm->tm_mon = i - 1;
288 
289                         if (*buf != 0 && isspace(*buf))
290                                 while (*ptr != 0 && !isspace(*ptr))
291                                         ptr++;
292                         break;
293 
294                 case 'Y':
295                 case 'y':
296                         if (*buf == 0 || isspace(*buf))
297                                 break;
298 
299                         if (!isdigit(*buf))
300                                 return 0;
301 
302                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
303                                 i *= 10;
304                                 i += *buf - '0';
305                         }
306                         if (c == 'Y')
307                                 i -= 1900;
308                         if (i < 0)
309                                 return 0;
310 
311                         tm->tm_year = i;
312 
313                         if (*buf != 0 && isspace(*buf))
314                                 while (*ptr != 0 && !isspace(*ptr))
315                                         ptr++;
316                         break;
317                 }
318         }
319 
320         return (char *) buf;
321 }
322 
323 
324