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[] =
| 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 "$FreeBSD: head/lib/libc/stdtime/strptime.c 71579 2001-01-24 13:01:12Z deischen $";
| 56 "$FreeBSD: head/lib/libc/stdtime/strptime.c 72168 2001-02-08 17:08:13Z phantom $";
|
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 "namespace.h" 68#include <time.h> 69#include <ctype.h> 70#include <string.h> 71#include <pthread.h> 72#include "un-namespace.h" 73#include "libc_private.h" 74#include "timelocal.h" 75 76static char * _strptime(const char *, const char *, struct tm *); 77 78static pthread_mutex_t gotgmt_mutex = PTHREAD_MUTEX_INITIALIZER; 79static int got_GMT; 80 81#define asizeof(a) (sizeof (a) / sizeof ((a)[0])) 82 83static char * 84_strptime(const char *buf, const char *fmt, struct tm *tm) 85{ 86 char c; 87 const char *ptr; 88 int i, 89 len; 90 int Ealternative, Oalternative;
| 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 "namespace.h" 68#include <time.h> 69#include <ctype.h> 70#include <string.h> 71#include <pthread.h> 72#include "un-namespace.h" 73#include "libc_private.h" 74#include "timelocal.h" 75 76static char * _strptime(const char *, const char *, struct tm *); 77 78static pthread_mutex_t gotgmt_mutex = PTHREAD_MUTEX_INITIALIZER; 79static int got_GMT; 80 81#define asizeof(a) (sizeof (a) / sizeof ((a)[0])) 82 83static char * 84_strptime(const char *buf, const char *fmt, struct tm *tm) 85{ 86 char c; 87 const char *ptr; 88 int i, 89 len; 90 int Ealternative, Oalternative;
|
| 91 struct lc_time_T *tptr = __get_current_time_locale();
|
91 92 ptr = fmt; 93 while (*ptr != 0) { 94 if (*buf == 0) 95 break; 96 97 c = *ptr++; 98 99 if (c != '%') { 100 if (isspace((unsigned char)c)) 101 while (*buf != 0 && isspace((unsigned char)*buf)) 102 buf++; 103 else if (c != *buf++) 104 return 0; 105 continue; 106 } 107 108 Ealternative = 0; 109 Oalternative = 0; 110label: 111 c = *ptr++; 112 switch (c) { 113 case 0: 114 case '%': 115 if (*buf++ != '%') 116 return 0; 117 break; 118 119 case '+':
| 92 93 ptr = fmt; 94 while (*ptr != 0) { 95 if (*buf == 0) 96 break; 97 98 c = *ptr++; 99 100 if (c != '%') { 101 if (isspace((unsigned char)c)) 102 while (*buf != 0 && isspace((unsigned char)*buf)) 103 buf++; 104 else if (c != *buf++) 105 return 0; 106 continue; 107 } 108 109 Ealternative = 0; 110 Oalternative = 0; 111label: 112 c = *ptr++; 113 switch (c) { 114 case 0: 115 case '%': 116 if (*buf++ != '%') 117 return 0; 118 break; 119 120 case '+':
|
120 buf = _strptime(buf, Locale->date_fmt, tm);
| 121 buf = _strptime(buf, tptr->date_fmt, tm);
|
121 if (buf == 0) 122 return 0; 123 break; 124 125 case 'C': 126 if (!isdigit((unsigned char)*buf)) 127 return 0; 128 129 /* XXX This will break for 3-digit centuries. */ 130 len = 2; 131 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 132 i *= 10; 133 i += *buf - '0'; 134 len--; 135 } 136 if (i < 19) 137 return 0; 138 139 tm->tm_year = i * 100 - 1900; 140 break; 141 142 case 'c': 143 /* NOTE: c_fmt is intentionally ignored */ 144 buf = _strptime(buf, "%a %Ef %T %Y", tm); 145 if (buf == 0) 146 return 0; 147 break; 148 149 case 'D': 150 buf = _strptime(buf, "%m/%d/%y", tm); 151 if (buf == 0) 152 return 0; 153 break; 154 155 case 'E': 156 if (Ealternative || Oalternative) 157 break; 158 Ealternative++; 159 goto label; 160 161 case 'O': 162 if (Ealternative || Oalternative) 163 break; 164 Oalternative++; 165 goto label; 166 167 case 'F': 168 case 'f': 169 if (!Ealternative) 170 break;
| 122 if (buf == 0) 123 return 0; 124 break; 125 126 case 'C': 127 if (!isdigit((unsigned char)*buf)) 128 return 0; 129 130 /* XXX This will break for 3-digit centuries. */ 131 len = 2; 132 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 133 i *= 10; 134 i += *buf - '0'; 135 len--; 136 } 137 if (i < 19) 138 return 0; 139 140 tm->tm_year = i * 100 - 1900; 141 break; 142 143 case 'c': 144 /* NOTE: c_fmt is intentionally ignored */ 145 buf = _strptime(buf, "%a %Ef %T %Y", tm); 146 if (buf == 0) 147 return 0; 148 break; 149 150 case 'D': 151 buf = _strptime(buf, "%m/%d/%y", tm); 152 if (buf == 0) 153 return 0; 154 break; 155 156 case 'E': 157 if (Ealternative || Oalternative) 158 break; 159 Ealternative++; 160 goto label; 161 162 case 'O': 163 if (Ealternative || Oalternative) 164 break; 165 Oalternative++; 166 goto label; 167 168 case 'F': 169 case 'f': 170 if (!Ealternative) 171 break;
|
171 buf = _strptime(buf, (c == 'f') ? Locale->Ef_fmt : Locale->EF_fmt, tm);
| 172 buf = _strptime(buf, (c == 'f') ? tptr->Ef_fmt : tptr->EF_fmt, tm);
|
172 if (buf == 0) 173 return 0; 174 break; 175 176 case 'R': 177 buf = _strptime(buf, "%H:%M", tm); 178 if (buf == 0) 179 return 0; 180 break; 181 182 case 'r': 183 buf = _strptime(buf, "%I:%M:%S %p", tm); 184 if (buf == 0) 185 return 0; 186 break; 187 188 case 'T': 189 buf = _strptime(buf, "%H:%M:%S", tm); 190 if (buf == 0) 191 return 0; 192 break; 193 194 case 'X':
| 173 if (buf == 0) 174 return 0; 175 break; 176 177 case 'R': 178 buf = _strptime(buf, "%H:%M", tm); 179 if (buf == 0) 180 return 0; 181 break; 182 183 case 'r': 184 buf = _strptime(buf, "%I:%M:%S %p", tm); 185 if (buf == 0) 186 return 0; 187 break; 188 189 case 'T': 190 buf = _strptime(buf, "%H:%M:%S", tm); 191 if (buf == 0) 192 return 0; 193 break; 194 195 case 'X':
|
195 buf = _strptime(buf, Locale->X_fmt, tm);
| 196 buf = _strptime(buf, tptr->X_fmt, tm);
|
196 if (buf == 0) 197 return 0; 198 break; 199 200 case 'x':
| 197 if (buf == 0) 198 return 0; 199 break; 200 201 case 'x':
|
201 buf = _strptime(buf, Locale->x_fmt, tm);
| 202 buf = _strptime(buf, tptr->x_fmt, tm);
|
202 if (buf == 0) 203 return 0; 204 break; 205 206 case 'j': 207 if (!isdigit((unsigned char)*buf)) 208 return 0; 209 210 len = 3; 211 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 212 i *= 10; 213 i += *buf - '0'; 214 len--; 215 } 216 if (i < 1 || i > 366) 217 return 0; 218 219 tm->tm_yday = i - 1; 220 break; 221 222 case 'M': 223 case 'S': 224 if (*buf == 0 || isspace((unsigned char)*buf)) 225 break; 226 227 if (!isdigit((unsigned char)*buf)) 228 return 0; 229 230 len = 2; 231 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 232 i *= 10; 233 i += *buf - '0'; 234 len--; 235 } 236 237 if (c == 'M') { 238 if (i > 59) 239 return 0; 240 tm->tm_min = i; 241 } else { 242 if (i > 60) 243 return 0; 244 tm->tm_sec = i; 245 } 246 247 if (*buf != 0 && isspace((unsigned char)*buf)) 248 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 249 ptr++; 250 break; 251 252 case 'H': 253 case 'I': 254 case 'k': 255 case 'l': 256 /* 257 * Of these, %l is the only specifier explicitly 258 * documented as not being zero-padded. However, 259 * there is no harm in allowing zero-padding. 260 * 261 * XXX The %l specifier may gobble one too many 262 * digits if used incorrectly. 263 */ 264 if (!isdigit((unsigned char)*buf)) 265 return 0; 266 267 len = 2; 268 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 269 i *= 10; 270 i += *buf - '0'; 271 len--; 272 } 273 if (c == 'H' || c == 'k') { 274 if (i > 23) 275 return 0; 276 } else if (i > 12) 277 return 0; 278 279 tm->tm_hour = i; 280 281 if (*buf != 0 && isspace((unsigned char)*buf)) 282 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 283 ptr++; 284 break; 285 286 case 'p': 287 /* 288 * XXX This is bogus if parsed before hour-related 289 * specifiers. 290 */
| 203 if (buf == 0) 204 return 0; 205 break; 206 207 case 'j': 208 if (!isdigit((unsigned char)*buf)) 209 return 0; 210 211 len = 3; 212 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 213 i *= 10; 214 i += *buf - '0'; 215 len--; 216 } 217 if (i < 1 || i > 366) 218 return 0; 219 220 tm->tm_yday = i - 1; 221 break; 222 223 case 'M': 224 case 'S': 225 if (*buf == 0 || isspace((unsigned char)*buf)) 226 break; 227 228 if (!isdigit((unsigned char)*buf)) 229 return 0; 230 231 len = 2; 232 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 233 i *= 10; 234 i += *buf - '0'; 235 len--; 236 } 237 238 if (c == 'M') { 239 if (i > 59) 240 return 0; 241 tm->tm_min = i; 242 } else { 243 if (i > 60) 244 return 0; 245 tm->tm_sec = i; 246 } 247 248 if (*buf != 0 && isspace((unsigned char)*buf)) 249 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 250 ptr++; 251 break; 252 253 case 'H': 254 case 'I': 255 case 'k': 256 case 'l': 257 /* 258 * Of these, %l is the only specifier explicitly 259 * documented as not being zero-padded. However, 260 * there is no harm in allowing zero-padding. 261 * 262 * XXX The %l specifier may gobble one too many 263 * digits if used incorrectly. 264 */ 265 if (!isdigit((unsigned char)*buf)) 266 return 0; 267 268 len = 2; 269 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 270 i *= 10; 271 i += *buf - '0'; 272 len--; 273 } 274 if (c == 'H' || c == 'k') { 275 if (i > 23) 276 return 0; 277 } else if (i > 12) 278 return 0; 279 280 tm->tm_hour = i; 281 282 if (*buf != 0 && isspace((unsigned char)*buf)) 283 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 284 ptr++; 285 break; 286 287 case 'p': 288 /* 289 * XXX This is bogus if parsed before hour-related 290 * specifiers. 291 */
|
291 len = strlen(Locale->am); 292 if (strncasecmp(buf, Locale->am, len) == 0) {
| 292 len = strlen(tptr->am); 293 if (strncasecmp(buf, tptr->am, len) == 0) {
|
293 if (tm->tm_hour > 12) 294 return 0; 295 if (tm->tm_hour == 12) 296 tm->tm_hour = 0; 297 buf += len; 298 break; 299 } 300
| 294 if (tm->tm_hour > 12) 295 return 0; 296 if (tm->tm_hour == 12) 297 tm->tm_hour = 0; 298 buf += len; 299 break; 300 } 301
|
301 len = strlen(Locale->pm); 302 if (strncasecmp(buf, Locale->pm, len) == 0) {
| 302 len = strlen(tptr->pm); 303 if (strncasecmp(buf, tptr->pm, len) == 0) {
|
303 if (tm->tm_hour > 12) 304 return 0; 305 if (tm->tm_hour != 12) 306 tm->tm_hour += 12; 307 buf += len; 308 break; 309 } 310 311 return 0; 312 313 case 'A': 314 case 'a':
| 304 if (tm->tm_hour > 12) 305 return 0; 306 if (tm->tm_hour != 12) 307 tm->tm_hour += 12; 308 buf += len; 309 break; 310 } 311 312 return 0; 313 314 case 'A': 315 case 'a':
|
315 for (i = 0; i < asizeof(Locale->weekday); i++) {
| 316 for (i = 0; i < asizeof(tptr->weekday); i++) {
|
316 if (c == 'A') {
| 317 if (c == 'A') {
|
317 len = strlen(Locale->weekday[i]);
| 318 len = strlen(tptr->weekday[i]);
|
318 if (strncasecmp(buf,
| 319 if (strncasecmp(buf,
|
319 Locale->weekday[i],
| 320 tptr->weekday[i],
|
320 len) == 0) 321 break; 322 } else {
| 321 len) == 0) 322 break; 323 } else {
|
323 len = strlen(Locale->wday[i]);
| 324 len = strlen(tptr->wday[i]);
|
324 if (strncasecmp(buf,
| 325 if (strncasecmp(buf,
|
325 Locale->wday[i],
| 326 tptr->wday[i],
|
326 len) == 0) 327 break; 328 } 329 }
| 327 len) == 0) 328 break; 329 } 330 }
|
330 if (i == asizeof(Locale->weekday))
| 331 if (i == asizeof(tptr->weekday))
|
331 return 0; 332 333 tm->tm_wday = i; 334 buf += len; 335 break; 336 337 case 'U': 338 case 'W': 339 /* 340 * XXX This is bogus, as we can not assume any valid 341 * information present in the tm structure at this 342 * point to calculate a real value, so just check the 343 * range for now. 344 */ 345 if (!isdigit((unsigned char)*buf)) 346 return 0; 347 348 len = 2; 349 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 350 i *= 10; 351 i += *buf - '0'; 352 len--; 353 } 354 if (i > 53) 355 return 0; 356 357 if (*buf != 0 && isspace((unsigned char)*buf)) 358 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 359 ptr++; 360 break; 361 362 case 'w': 363 if (!isdigit((unsigned char)*buf)) 364 return 0; 365 366 i = *buf - '0'; 367 if (i > 6) 368 return 0; 369 370 tm->tm_wday = i; 371 372 if (*buf != 0 && isspace((unsigned char)*buf)) 373 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 374 ptr++; 375 break; 376 377 case 'd': 378 case 'e': 379 /* 380 * The %e specifier is explicitly documented as not 381 * being zero-padded but there is no harm in allowing 382 * such padding. 383 * 384 * XXX The %e specifier may gobble one too many 385 * digits if used incorrectly. 386 */ 387 if (!isdigit((unsigned char)*buf)) 388 return 0; 389 390 len = 2; 391 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 392 i *= 10; 393 i += *buf - '0'; 394 len--; 395 } 396 if (i > 31) 397 return 0; 398 399 tm->tm_mday = i; 400 401 if (*buf != 0 && isspace((unsigned char)*buf)) 402 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 403 ptr++; 404 break; 405 406 case 'B': 407 case 'b': 408 case 'h':
| 332 return 0; 333 334 tm->tm_wday = i; 335 buf += len; 336 break; 337 338 case 'U': 339 case 'W': 340 /* 341 * XXX This is bogus, as we can not assume any valid 342 * information present in the tm structure at this 343 * point to calculate a real value, so just check the 344 * range for now. 345 */ 346 if (!isdigit((unsigned char)*buf)) 347 return 0; 348 349 len = 2; 350 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 351 i *= 10; 352 i += *buf - '0'; 353 len--; 354 } 355 if (i > 53) 356 return 0; 357 358 if (*buf != 0 && isspace((unsigned char)*buf)) 359 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 360 ptr++; 361 break; 362 363 case 'w': 364 if (!isdigit((unsigned char)*buf)) 365 return 0; 366 367 i = *buf - '0'; 368 if (i > 6) 369 return 0; 370 371 tm->tm_wday = i; 372 373 if (*buf != 0 && isspace((unsigned char)*buf)) 374 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 375 ptr++; 376 break; 377 378 case 'd': 379 case 'e': 380 /* 381 * The %e specifier is explicitly documented as not 382 * being zero-padded but there is no harm in allowing 383 * such padding. 384 * 385 * XXX The %e specifier may gobble one too many 386 * digits if used incorrectly. 387 */ 388 if (!isdigit((unsigned char)*buf)) 389 return 0; 390 391 len = 2; 392 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 393 i *= 10; 394 i += *buf - '0'; 395 len--; 396 } 397 if (i > 31) 398 return 0; 399 400 tm->tm_mday = i; 401 402 if (*buf != 0 && isspace((unsigned char)*buf)) 403 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 404 ptr++; 405 break; 406 407 case 'B': 408 case 'b': 409 case 'h':
|
409 for (i = 0; i < asizeof(Locale->month); i++) {
| 410 for (i = 0; i < asizeof(tptr->month); i++) {
|
410 if (Oalternative) { 411 if (c == 'B') {
| 411 if (Oalternative) { 412 if (c == 'B') {
|
412 len = strlen(Locale->alt_month[i]);
| 413 len = strlen(tptr->alt_month[i]);
|
413 if (strncasecmp(buf,
| 414 if (strncasecmp(buf,
|
414 Locale->alt_month[i],
| 415 tptr->alt_month[i],
|
415 len) == 0) 416 break; 417 } 418 } else { 419 if (c == 'B') {
| 416 len) == 0) 417 break; 418 } 419 } else { 420 if (c == 'B') {
|
420 len = strlen(Locale->month[i]);
| 421 len = strlen(tptr->month[i]);
|
421 if (strncasecmp(buf,
| 422 if (strncasecmp(buf,
|
422 Locale->month[i],
| 423 tptr->month[i],
|
423 len) == 0) 424 break; 425 } else {
| 424 len) == 0) 425 break; 426 } else {
|
426 len = strlen(Locale->mon[i]);
| 427 len = strlen(tptr->mon[i]);
|
427 if (strncasecmp(buf,
| 428 if (strncasecmp(buf,
|
428 Locale->mon[i],
| 429 tptr->mon[i],
|
429 len) == 0) 430 break; 431 } 432 } 433 }
| 430 len) == 0) 431 break; 432 } 433 } 434 }
|
434 if (i == asizeof(Locale->month))
| 435 if (i == asizeof(tptr->month))
|
435 return 0; 436 437 tm->tm_mon = i; 438 buf += len; 439 break; 440 441 case 'm': 442 if (!isdigit((unsigned char)*buf)) 443 return 0; 444 445 len = 2; 446 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 447 i *= 10; 448 i += *buf - '0'; 449 len--; 450 } 451 if (i < 1 || i > 12) 452 return 0; 453 454 tm->tm_mon = i - 1; 455 456 if (*buf != 0 && isspace((unsigned char)*buf)) 457 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 458 ptr++; 459 break; 460 461 case 'Y': 462 case 'y': 463 if (*buf == 0 || isspace((unsigned char)*buf)) 464 break; 465 466 if (!isdigit((unsigned char)*buf)) 467 return 0; 468 469 len = (c == 'Y') ? 4 : 2; 470 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 471 i *= 10; 472 i += *buf - '0'; 473 len--; 474 } 475 if (c == 'Y') 476 i -= 1900; 477 if (c == 'y' && i < 69) 478 i += 100; 479 if (i < 0) 480 return 0; 481 482 tm->tm_year = i; 483 484 if (*buf != 0 && isspace((unsigned char)*buf)) 485 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 486 ptr++; 487 break; 488 489 case 'Z': 490 { 491 const char *cp; 492 char *zonestr; 493 494 for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/} 495 if (cp - buf) { 496 zonestr = alloca(cp - buf + 1); 497 strncpy(zonestr, buf, cp - buf); 498 zonestr[cp - buf] = '\0'; 499 tzset(); 500 if (0 == strcmp(zonestr, "GMT")) { 501 got_GMT = 1; 502 } else if (0 == strcmp(zonestr, tzname[0])) { 503 tm->tm_isdst = 0; 504 } else if (0 == strcmp(zonestr, tzname[1])) { 505 tm->tm_isdst = 1; 506 } else { 507 return 0; 508 } 509 buf += cp - buf; 510 } 511 } 512 break; 513 } 514 } 515 return (char *)buf; 516} 517 518 519char * 520strptime(const char *buf, const char *fmt, struct tm *tm) 521{ 522 char *ret; 523 524 if (__isthreaded) 525 _pthread_mutex_lock(&gotgmt_mutex); 526 527 got_GMT = 0; 528 ret = _strptime(buf, fmt, tm); 529 if (ret && got_GMT) { 530 time_t t = timegm(tm); 531 localtime_r(&t, tm); 532 got_GMT = 0; 533 } 534 535 if (__isthreaded) 536 _pthread_mutex_unlock(&gotgmt_mutex); 537 538 return ret; 539}
| 436 return 0; 437 438 tm->tm_mon = i; 439 buf += len; 440 break; 441 442 case 'm': 443 if (!isdigit((unsigned char)*buf)) 444 return 0; 445 446 len = 2; 447 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 448 i *= 10; 449 i += *buf - '0'; 450 len--; 451 } 452 if (i < 1 || i > 12) 453 return 0; 454 455 tm->tm_mon = i - 1; 456 457 if (*buf != 0 && isspace((unsigned char)*buf)) 458 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 459 ptr++; 460 break; 461 462 case 'Y': 463 case 'y': 464 if (*buf == 0 || isspace((unsigned char)*buf)) 465 break; 466 467 if (!isdigit((unsigned char)*buf)) 468 return 0; 469 470 len = (c == 'Y') ? 4 : 2; 471 for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { 472 i *= 10; 473 i += *buf - '0'; 474 len--; 475 } 476 if (c == 'Y') 477 i -= 1900; 478 if (c == 'y' && i < 69) 479 i += 100; 480 if (i < 0) 481 return 0; 482 483 tm->tm_year = i; 484 485 if (*buf != 0 && isspace((unsigned char)*buf)) 486 while (*ptr != 0 && !isspace((unsigned char)*ptr)) 487 ptr++; 488 break; 489 490 case 'Z': 491 { 492 const char *cp; 493 char *zonestr; 494 495 for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/} 496 if (cp - buf) { 497 zonestr = alloca(cp - buf + 1); 498 strncpy(zonestr, buf, cp - buf); 499 zonestr[cp - buf] = '\0'; 500 tzset(); 501 if (0 == strcmp(zonestr, "GMT")) { 502 got_GMT = 1; 503 } else if (0 == strcmp(zonestr, tzname[0])) { 504 tm->tm_isdst = 0; 505 } else if (0 == strcmp(zonestr, tzname[1])) { 506 tm->tm_isdst = 1; 507 } else { 508 return 0; 509 } 510 buf += cp - buf; 511 } 512 } 513 break; 514 } 515 } 516 return (char *)buf; 517} 518 519 520char * 521strptime(const char *buf, const char *fmt, struct tm *tm) 522{ 523 char *ret; 524 525 if (__isthreaded) 526 _pthread_mutex_lock(&gotgmt_mutex); 527 528 got_GMT = 0; 529 ret = _strptime(buf, fmt, tm); 530 if (ret && got_GMT) { 531 time_t t = timegm(tm); 532 localtime_r(&t, tm); 533 got_GMT = 0; 534 } 535 536 if (__isthreaded) 537 _pthread_mutex_unlock(&gotgmt_mutex); 538 539 return ret; 540}
|