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