1 /* 2 * Powerdog Industries kindly requests feedback from anyone modifying 3 * this function: 4 * 5 * Date: Thu, 05 Jun 1997 23:17:17 -0400 6 * From: Kevin Ruddy <kevin.ruddy@powerdog.com> 7 * To: James FitzGibbon <james@nexis.net> 8 * Subject: Re: Use of your strptime(3) code (fwd) 9 * 10 * The reason for the "no mod" clause was so that modifications would 11 * come back and we could integrate them and reissue so that a wider 12 * audience could use it (thereby spreading the wealth). This has 13 * made it possible to get strptime to work on many operating systems. 14 * I'm not sure why that's "plain unacceptable" to the FreeBSD team. 15 * 16 * Anyway, you can change it to "with or without modification" as 17 * you see fit. Enjoy. 18 * 19 * Kevin Ruddy 20 * Powerdog Industries, Inc. 21 */ 22 /* 23 * Copyright (c) 1994 Powerdog Industries. All rights reserved. 24 * 25 * Redistribution and use in source and binary forms, with or without 26 * modification, are permitted provided that the following conditions 27 * are met: 28 * 1. Redistributions of source code must retain the above copyright 29 * notice, this list of conditions and the following disclaimer. 30 * 2. Redistributions in binary form must reproduce the above copyright 31 * notice, this list of conditions and the following disclaimer 32 * in the documentation and/or other materials provided with the 33 * distribution. 34 * 3. All advertising materials mentioning features or use of this 35 * software must display the following acknowledgement: 36 * This product includes software developed by Powerdog Industries. 37 * 4. The name of Powerdog Industries may not be used to endorse or 38 * promote products derived from this software without specific prior 39 * written permission. 40 * 41 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY 42 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 44 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE 45 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 46 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 47 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 48 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 49 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 50 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 51 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 */ 53 54 #ifdef LIBC_RCS 55 static const char rcsid[] = 56 "$Id: strptime.c,v 1.5 1999/04/25 01:42:18 wes Exp $"; 57 #endif 58 59 #ifndef lint 60 #ifndef NOID 61 static char copyright[] = 62 "@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved."; 63 static char sccsid[] = "@(#)strptime.c 0.1 (Powerdog) 94/03/27"; 64 #endif /* !defined NOID */ 65 #endif /* not lint */ 66 67 #include <time.h> 68 #include <ctype.h> 69 #include <string.h> 70 #include "timelocal.h" 71 72 #define asizeof(a) (sizeof (a) / sizeof ((a)[0])) 73 74 char * 75 strptime(const char *buf, const char *fmt, struct tm *tm) 76 { 77 char c; 78 const char *ptr; 79 int i, 80 len; 81 82 ptr = fmt; 83 while (*ptr != 0) { 84 if (*buf == 0) 85 break; 86 87 c = *ptr++; 88 89 if (c != '%') { 90 if (isspace((unsigned char)c)) 91 while (*buf != 0 && isspace((unsigned char)*buf)) 92 buf++; 93 else if (c != *buf++) 94 return 0; 95 continue; 96 } 97 98 c = *ptr++; 99 switch (c) { 100 case 0: 101 case '%': 102 if (*buf++ != '%') 103 return 0; 104 break; 105 106 case 'C': 107 buf = strptime(buf, Locale->date_fmt, tm); 108 if (buf == 0) 109 return 0; 110 break; 111 112 case 'c': 113 buf = strptime(buf, "%x %X", tm); 114 if (buf == 0) 115 return 0; 116 break; 117 118 case 'D': 119 buf = strptime(buf, "%m/%d/%y", tm); 120 if (buf == 0) 121 return 0; 122 break; 123 124 case 'R': 125 buf = strptime(buf, "%H:%M", tm); 126 if (buf == 0) 127 return 0; 128 break; 129 130 case 'r': 131 buf = strptime(buf, "%I:%M:%S %p", tm); 132 if (buf == 0) 133 return 0; 134 break; 135 136 case 'T': 137 buf = strptime(buf, "%H:%M:%S", tm); 138 if (buf == 0) 139 return 0; 140 break; 141 142 case 'X': 143 buf = strptime(buf, Locale->X_fmt, tm); 144 if (buf == 0) 145 return 0; 146 break; 147 148 case 'x': 149 buf = strptime(buf, Locale->x_fmt, tm); 150 if (buf == 0) 151 return 0; 152 break; 153 154 case 'j': 155 if (!isdigit((unsigned char)*buf)) 156 return 0; 157 158 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 159 i *= 10; 160 i += *buf - '0'; 161 } 162 if (i > 365) 163 return 0; 164 165 tm->tm_yday = i; 166 break; 167 168 case 'M': 169 case 'S': 170 if (*buf == 0 || isspace((unsigned char)*buf)) 171 break; 172 173 if (!isdigit((unsigned char)*buf)) 174 return 0; 175 176 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 177 i *= 10; 178 i += *buf - '0'; 179 } 180 if (i > 59) 181 return 0; 182 183 if (c == 'M') 184 tm->tm_min = i; 185 else 186 tm->tm_sec = i; 187 188 if (*buf != 0 && isspace((unsigned char)*buf)) 189 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 190 ptr++; 191 break; 192 193 case 'H': 194 case 'I': 195 case 'k': 196 case 'l': 197 if (!isdigit((unsigned char)*buf)) 198 return 0; 199 200 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 201 i *= 10; 202 i += *buf - '0'; 203 } 204 if (c == 'H' || c == 'k') { 205 if (i > 23) 206 return 0; 207 } else if (i > 11) 208 return 0; 209 210 tm->tm_hour = i; 211 212 if (*buf != 0 && isspace((unsigned char)*buf)) 213 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 214 ptr++; 215 break; 216 217 case 'p': 218 len = strlen(Locale->am); 219 if (strncasecmp(buf, Locale->am, len) == 0) { 220 if (tm->tm_hour > 12) 221 return 0; 222 if (tm->tm_hour == 12) 223 tm->tm_hour = 0; 224 buf += len; 225 break; 226 } 227 228 len = strlen(Locale->pm); 229 if (strncasecmp(buf, Locale->pm, len) == 0) { 230 if (tm->tm_hour > 12) 231 return 0; 232 if (tm->tm_hour != 12) 233 tm->tm_hour += 12; 234 buf += len; 235 break; 236 } 237 238 return 0; 239 240 case 'A': 241 case 'a': 242 for (i = 0; i < asizeof(Locale->weekday); i++) { 243 len = strlen(Locale->weekday[i]); 244 if (strncasecmp(buf, 245 Locale->weekday[i], 246 len) == 0) 247 break; 248 249 len = strlen(Locale->wday[i]); 250 if (strncasecmp(buf, 251 Locale->wday[i], 252 len) == 0) 253 break; 254 } 255 if (i == asizeof(Locale->weekday)) 256 return 0; 257 258 tm->tm_wday = i; 259 buf += len; 260 break; 261 262 case 'd': 263 case 'e': 264 if (!isdigit((unsigned char)*buf)) 265 return 0; 266 267 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 268 i *= 10; 269 i += *buf - '0'; 270 } 271 if (i > 31) 272 return 0; 273 274 tm->tm_mday = i; 275 276 if (*buf != 0 && isspace((unsigned char)*buf)) 277 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 278 ptr++; 279 break; 280 281 case 'B': 282 case 'b': 283 case 'h': 284 for (i = 0; i < asizeof(Locale->month); i++) { 285 len = strlen(Locale->month[i]); 286 if (strncasecmp(buf, 287 Locale->month[i], 288 len) == 0) 289 break; 290 291 len = strlen(Locale->mon[i]); 292 if (strncasecmp(buf, 293 Locale->mon[i], 294 len) == 0) 295 break; 296 } 297 if (i == asizeof(Locale->month)) 298 return 0; 299 300 tm->tm_mon = i; 301 buf += len; 302 break; 303 304 case 'm': 305 if (!isdigit((unsigned char)*buf)) 306 return 0; 307 308 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 309 i *= 10; 310 i += *buf - '0'; 311 } 312 if (i < 1 || i > 12) 313 return 0; 314 315 tm->tm_mon = i - 1; 316 317 if (*buf != 0 && isspace((unsigned char)*buf)) 318 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 319 ptr++; 320 break; 321 322 case 'Y': 323 case 'y': 324 if (*buf == 0 || isspace((unsigned char)*buf)) 325 break; 326 327 if (!isdigit((unsigned char)*buf)) 328 return 0; 329 330 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 331 i *= 10; 332 i += *buf - '0'; 333 } 334 if (c == 'Y') 335 i -= 1900; 336 if (c == 'y' && i < 69) 337 i += 100; 338 if (i < 0) 339 return 0; 340 341 tm->tm_year = i; 342 343 if (*buf != 0 && isspace((unsigned char)*buf)) 344 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 345 ptr++; 346 break; 347 } 348 } 349 350 return (char *)buf; 351 } 352