1 /* vi:ai:et:ts=8 sw=2
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 /** \file
35 * \brief strptime() replacement
36 */
37
38
39 #include "wzd_all.h"
40
41 #include <ctype.h>
42 #include <string.h>
43 #include <time.h>
44
45 #include "wzd_strptime.h"
46
47 #ifndef HAVE_STRPTIME
48
49 extern void ascii_lower(char * s, unsigned int length);
50 #define lowercase_string(x) ascii_lower(x,strlen(x))
51
52
53 #define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
54
55
56 #ifndef sun
57 struct dtconv {
58 char *abbrev_month_names[12];
59 char *month_names[12];
60 char *abbrev_weekday_names[7];
61 char *weekday_names[7];
62 char *time_format;
63 char *sdate_format;
64 char *dtime_format;
65 char *am_string;
66 char *pm_string;
67 char *ldate_format;
68 };
69 #endif
70
71 static struct dtconv En_US = {
72 { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
73 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" },
74 { "January", "February", "March", "April",
75 "May", "June", "July", "August",
76 "September", "October", "November", "December" },
77 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
78 { "Sunday", "Monday", "Tuesday", "Wednesday",
79 "Thursday", "Friday", "Saturday" },
80 "%H:%M:%S",
81 "%m/%d/%y",
82 "%a %b %e %T %Z %Y",
83 "AM",
84 "PM",
85 "%A, %B, %e, %Y"
86 };
87
88 #ifdef SUNOS4
89 extern int strncasecmp();
90 #endif
91
92 char *
strptime(char * buf,char * fmt,struct tm * tm)93 strptime(char *buf, char *fmt, struct tm *tm)
94 {
95 char c, *ptr;
96 int i, j, len;
97
98 ptr = fmt;
99 while (*ptr != 0) {
100 if (*buf == 0)
101 break;
102
103 c = *ptr++;
104
105 if (c != '%') {
106 if (isspace(c))
107 while (*buf != 0 && isspace(*buf))
108 buf++;
109 else if (c != *buf++)
110 return 0;
111 continue;
112 }
113
114 c = *ptr++;
115 switch (c) {
116 case 0:
117 case '%':
118 if (*buf++ != '%')
119 return 0;
120 break;
121
122 case 'C':
123 buf = strptime(buf, En_US.ldate_format, tm);
124 if (buf == 0)
125 return 0;
126 break;
127
128 case 'c':
129 buf = strptime(buf, "%x %X", tm);
130 if (buf == 0)
131 return 0;
132 break;
133
134 case 'D':
135 buf = strptime(buf, "%m/%d/%y", tm);
136 if (buf == 0)
137 return 0;
138 break;
139
140 case 'R':
141 buf = strptime(buf, "%H:%M", tm);
142 if (buf == 0)
143 return 0;
144 break;
145
146 case 'r':
147 buf = strptime(buf, "%I:%M:%S %p", tm);
148 if (buf == 0)
149 return 0;
150 break;
151
152 case 'T':
153 buf = strptime(buf, "%H:%M:%S", tm);
154 if (buf == 0)
155 return 0;
156 break;
157
158 case 'X':
159 buf = strptime(buf, En_US.time_format, tm);
160 if (buf == 0)
161 return 0;
162 break;
163
164 case 'x':
165 buf = strptime(buf, En_US.sdate_format, tm);
166 if (buf == 0)
167 return 0;
168 break;
169
170 case 'j':
171 if (!isdigit(*buf))
172 return 0;
173
174 for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
175 i *= 10;
176 i += *buf - '0';
177 }
178 if (i > 365)
179 return 0;
180
181 tm->tm_yday = i;
182 break;
183
184 case 'M':
185 case 'S':
186 if (*buf == 0 || isspace(*buf))
187 break;
188
189 if (!isdigit(*buf))
190 return 0;
191
192 for (j=0,i = 0; *buf != 0 && isdigit(*buf) && j<2; j++,buf++) {
193 i *= 10;
194 i += *buf - '0';
195 }
196 if (i > 59)
197 return 0;
198
199 if (c == 'M')
200 tm->tm_min = i;
201 else
202 tm->tm_sec = i;
203
204 if (*buf != 0 && isspace(*buf))
205 while (*ptr != 0 && !isspace(*ptr))
206 ptr++;
207 break;
208
209 case 'H':
210 case 'I':
211 case 'k':
212 case 'l':
213 if (!isdigit(*buf))
214 return 0;
215
216 for (j=0,i = 0; *buf != 0 && isdigit(*buf) && j<2; j++,buf++) {
217 i *= 10;
218 i += *buf - '0';
219 }
220 if (c == 'H' || c == 'k') {
221 if (i > 23)
222 return 0;
223 } else if (i > 11)
224 return 0;
225
226 tm->tm_hour = i;
227
228 if (*buf != 0 && isspace(*buf))
229 while (*ptr != 0 && !isspace(*ptr))
230 ptr++;
231 break;
232
233 case 'p':
234 len = strlen(En_US.am_string);
235 lowercase_string( buf );
236
237 if (strncmp(buf, En_US.am_string, len) == 0) {
238 if (tm->tm_hour > 12)
239 return 0;
240 if (tm->tm_hour == 12)
241 tm->tm_hour = 0;
242 buf += len;
243 break;
244 }
245
246 len = strlen(En_US.pm_string);
247
248 if (strncmp(buf, En_US.pm_string, len) == 0) {
249 if (tm->tm_hour > 12)
250 return 0;
251 if (tm->tm_hour != 12)
252 tm->tm_hour += 12;
253 buf += len;
254 break;
255 }
256
257 return 0;
258
259 case 'A':
260 case 'a':
261 for (i = 0; i < asizeof(En_US.weekday_names); i++) {
262 len = strlen(En_US.weekday_names[i]);
263
264 lowercase_string( buf );
265
266 if (strncmp(buf,
267 En_US.weekday_names[i],
268 len) == 0)
269 break;
270
271 len = strlen(En_US.abbrev_weekday_names[i]);
272 if (strncmp(buf,
273 En_US.abbrev_weekday_names[i],
274 len) == 0)
275 break;
276 }
277 if (i == asizeof(En_US.weekday_names))
278 return 0;
279
280 tm->tm_wday = i;
281 buf += len;
282 break;
283
284 case 'd':
285 case 'e':
286 if (!isdigit(*buf))
287 return 0;
288
289 for (j=0,i = 0; *buf != 0 && isdigit(*buf) && j<2; j++,buf++) {
290 i *= 10;
291 i += *buf - '0';
292 }
293 if (i > 31)
294 return 0;
295
296 tm->tm_mday = i;
297
298 if (*buf != 0 && isspace(*buf))
299 while (*ptr != 0 && !isspace(*ptr))
300 ptr++;
301 break;
302
303 case 'B':
304 case 'b':
305 case 'h':
306 for (i = 0; i < asizeof(En_US.month_names); i++) {
307 len = strlen(En_US.month_names[i]);
308
309 lowercase_string( buf );
310 if (strncmp(buf, En_US.month_names[i],len) == 0)
311 break;
312
313 len = strlen(En_US.abbrev_month_names[i]);
314 if (strncmp(buf,
315 En_US.abbrev_month_names[i],
316 len) == 0)
317 break;
318 }
319 if (i == asizeof(En_US.month_names))
320 return 0;
321
322 tm->tm_mon = i;
323 buf += len;
324 break;
325
326 case 'm':
327 if (!isdigit(*buf))
328 return 0;
329
330 for (j=0,i = 0; *buf != 0 && isdigit(*buf) && j<2; j++,buf++) {
331 i *= 10;
332 i += *buf - '0';
333 }
334 if (i < 1 || i > 12)
335 return 0;
336
337 tm->tm_mon = i - 1;
338
339 if (*buf != 0 && isspace(*buf))
340 while (*ptr != 0 && !isspace(*ptr))
341 ptr++;
342 break;
343
344 case 'Y':
345 case 'y':
346 if (*buf == 0 || isspace(*buf))
347 break;
348
349 if (!isdigit(*buf))
350 return 0;
351
352 for (j=0,i = 0; *buf != 0 && isdigit(*buf) && j<((c=='Y')?4:2); j++,buf++) {
353 i *= 10;
354 i += *buf - '0';
355 }
356
357 if (c == 'Y')
358 i -= 1900;
359 else if (i < 69) /*c=='y', 00-68 is for 20xx, the rest is for 19xx*/
360 i += 100;
361
362 if (i < 0)
363 return 0;
364
365 tm->tm_year = i;
366
367 if (*buf != 0 && isspace(*buf))
368 while (*ptr != 0 && !isspace(*ptr))
369 ptr++;
370 break;
371 }
372 }
373
374 return buf;
375 }
376
377 #endif /* ndef HAVE_STRPTIME */
378