strptime.c revision 48550
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 55static const char rcsid[] = 56 "$Id: strptime.c,v 1.6 1999/04/25 07:28:39 wes Exp $"; 57#endif 58 59#ifndef lint 60#ifndef NOID 61static char copyright[] = 62"@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved."; 63static 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 74static int got_GMT = 0; 75 76char * 77strptime(const char *buf, const char *fmt, struct tm *tm) 78{ 79 char c; 80 const char *ptr; 81 int i, 82 len; 83 84 ptr = fmt; 85 while (*ptr != 0) { 86 if (*buf == 0) 87 break; 88 89 c = *ptr++; 90 91 if (c != '%') { 92 if (isspace((unsigned char)c)) 93 while (*buf != 0 && isspace((unsigned char)*buf)) 94 buf++; 95 else if (c != *buf++) 96 return 0; 97 continue; 98 } 99 100 c = *ptr++; 101 switch (c) { 102 case 0: 103 case '%': 104 if (*buf++ != '%') 105 return 0; 106 break; 107 108 case 'C': 109 buf = strptime(buf, Locale->date_fmt, tm); 110 if (buf == 0) 111 return 0; 112 break; 113 114 case 'c': 115 buf = strptime(buf, "%x %X", tm); 116 if (buf == 0) 117 return 0; 118 break; 119 120 case 'D': 121 buf = strptime(buf, "%m/%d/%y", tm); 122 if (buf == 0) 123 return 0; 124 break; 125 126 case 'R': 127 buf = strptime(buf, "%H:%M", tm); 128 if (buf == 0) 129 return 0; 130 break; 131 132 case 'r': 133 buf = strptime(buf, "%I:%M:%S %p", tm); 134 if (buf == 0) 135 return 0; 136 break; 137 138 case 'T': 139 buf = strptime(buf, "%H:%M:%S", tm); 140 if (buf == 0) 141 return 0; 142 break; 143 144 case 'X': 145 buf = strptime(buf, Locale->X_fmt, tm); 146 if (buf == 0) 147 return 0; 148 break; 149 150 case 'x': 151 buf = strptime(buf, Locale->x_fmt, tm); 152 if (buf == 0) 153 return 0; 154 break; 155 156 case 'j': 157 if (!isdigit((unsigned char)*buf)) 158 return 0; 159 160 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 161 i *= 10; 162 i += *buf - '0'; 163 } 164 if (i > 365) 165 return 0; 166 167 tm->tm_yday = i; 168 break; 169 170 case 'M': 171 case 'S': 172 if (*buf == 0 || isspace((unsigned char)*buf)) 173 break; 174 175 if (!isdigit((unsigned char)*buf)) 176 return 0; 177 178 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 179 i *= 10; 180 i += *buf - '0'; 181 } 182 if (i > 59) 183 return 0; 184 185 if (c == 'M') 186 tm->tm_min = i; 187 else 188 tm->tm_sec = i; 189 190 if (*buf != 0 && isspace((unsigned char)*buf)) 191 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 192 ptr++; 193 break; 194 195 case 'H': 196 case 'I': 197 case 'k': 198 case 'l': 199 if (!isdigit((unsigned char)*buf)) 200 return 0; 201 202 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 203 i *= 10; 204 i += *buf - '0'; 205 } 206 if (c == 'H' || c == 'k') { 207 if (i > 23) 208 return 0; 209 } else if (i > 11) 210 return 0; 211 212 tm->tm_hour = i; 213 214 if (*buf != 0 && isspace((unsigned char)*buf)) 215 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 216 ptr++; 217 break; 218 219 case 'p': 220 len = strlen(Locale->am); 221 if (strncasecmp(buf, Locale->am, len) == 0) { 222 if (tm->tm_hour > 12) 223 return 0; 224 if (tm->tm_hour == 12) 225 tm->tm_hour = 0; 226 buf += len; 227 break; 228 } 229 230 len = strlen(Locale->pm); 231 if (strncasecmp(buf, Locale->pm, len) == 0) { 232 if (tm->tm_hour > 12) 233 return 0; 234 if (tm->tm_hour != 12) 235 tm->tm_hour += 12; 236 buf += len; 237 break; 238 } 239 240 return 0; 241 242 case 'A': 243 case 'a': 244 for (i = 0; i < asizeof(Locale->weekday); i++) { 245 len = strlen(Locale->weekday[i]); 246 if (strncasecmp(buf, 247 Locale->weekday[i], 248 len) == 0) 249 break; 250 251 len = strlen(Locale->wday[i]); 252 if (strncasecmp(buf, 253 Locale->wday[i], 254 len) == 0) 255 break; 256 } 257 if (i == asizeof(Locale->weekday)) 258 return 0; 259 260 tm->tm_wday = i; 261 buf += len; 262 break; 263 264 case 'd': 265 case 'e': 266 if (!isdigit((unsigned char)*buf)) 267 return 0; 268 269 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 270 i *= 10; 271 i += *buf - '0'; 272 } 273 if (i > 31) 274 return 0; 275 276 tm->tm_mday = i; 277 278 if (*buf != 0 && isspace((unsigned char)*buf)) 279 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 280 ptr++; 281 break; 282 283 case 'B': 284 case 'b': 285 case 'h': 286 for (i = 0; i < asizeof(Locale->month); i++) { 287 len = strlen(Locale->month[i]); 288 if (strncasecmp(buf, 289 Locale->month[i], 290 len) == 0) 291 break; 292 293 len = strlen(Locale->mon[i]); 294 if (strncasecmp(buf, 295 Locale->mon[i], 296 len) == 0) 297 break; 298 } 299 if (i == asizeof(Locale->month)) 300 return 0; 301 302 tm->tm_mon = i; 303 buf += len; 304 break; 305 306 case 'm': 307 if (!isdigit((unsigned char)*buf)) 308 return 0; 309 310 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 311 i *= 10; 312 i += *buf - '0'; 313 } 314 if (i < 1 || i > 12) 315 return 0; 316 317 tm->tm_mon = i - 1; 318 319 if (*buf != 0 && isspace((unsigned char)*buf)) 320 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 321 ptr++; 322 break; 323 324 case 'Y': 325 case 'y': 326 if (*buf == 0 || isspace((unsigned char)*buf)) 327 break; 328 329 if (!isdigit((unsigned char)*buf)) 330 return 0; 331 332 for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 333 i *= 10; 334 i += *buf - '0'; 335 } 336 if (c == 'Y') 337 i -= 1900; 338 if (c == 'y' && i < 69) 339 i += 100; 340 if (i < 0) 341 return 0; 342 343 tm->tm_year = i; 344 345 if (*buf != 0 && isspace((unsigned char)*buf)) 346 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 347 ptr++; 348 break; 349 350 case 'Z': 351 { 352 const char *cp; 353 char *zonestr; 354 355 for (cp = buf; *cp && isupper(*cp); ++cp) {/*empty*/} 356 if (cp - buf) { 357 zonestr = alloca(cp - buf + 1); 358 strncpy(zonestr, buf, cp - buf); 359 zonestr[cp - buf] = '\0'; 360 tzset(); 361 if (0 == strcmp(zonestr, "GMT")) { 362 got_GMT = 1; 363 } else if (0 == strcmp(zonestr, tzname[0])) { 364 tm->tm_isdst = 0; 365 } else if (0 == strcmp(zonestr, tzname[1])) { 366 tm->tm_isdst = 1; 367 } else { 368 return 0; 369 } 370 buf += cp - buf; 371 } 372 } 373 break; 374 } 375 } 376 377 if (got_GMT) { 378 time_t t = timegm(tm); 379 localtime_r(&t, tm); 380 } 381 return (char *)buf; 382} 383