00001 #include "misc.h"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #if !defined(_WIN32)
00046 #include <sys/cdefs.h>
00047 #endif
00048
00049 #if defined(LIBC_SCCS) && !defined(lint)
00050 __RCSID("$NetBSD: strptime.c,v 1.25 2005/11/29 03:12:00 christos Exp $");
00051 #endif
00052
00053 #if !defined(_WIN32)
00054 #include "namespace.h"
00055 #include <sys/localedef.h>
00056 #else
00057 typedef unsigned char u_char;
00058 typedef unsigned int uint;
00059 #endif
00060 #include <ctype.h>
00061 #include <locale.h>
00062 #include <string.h>
00063 #include <time.h>
00064 #if !defined(_WIN32)
00065 #include <tzfile.h>
00066 #endif
00067
00068 #ifdef __weak_alias
00069 __weak_alias(strptime,_strptime)
00070 #endif
00071
00072 #if !defined(_WIN32)
00073 #define _ctloc(x) (_CurrentTimeLocale->x)
00074 #else
00075 #define _ctloc(x) (x)
00076 const char *abday[] = {
00077 "Sun", "Mon", "Tue", "Wed",
00078 "Thu", "Fri", "Sat"
00079 };
00080 const char *day[] = {
00081 "Sunday", "Monday", "Tuesday", "Wednesday",
00082 "Thursday", "Friday", "Saturday"
00083 };
00084 const char *abmon[] = {
00085 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00086 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00087 };
00088 const char *mon[] = {
00089 "January", "February", "March", "April", "May", "June",
00090 "July", "August", "September", "October", "November", "December"
00091 };
00092 const char *am_pm[] = {
00093 "AM", "PM"
00094 };
00095 char *d_t_fmt = "%a %Ef %T %Y";
00096 char *t_fmt_ampm = "%I:%M:%S %p";
00097 char *t_fmt = "%H:%M:%S";
00098 char *d_fmt = "%m/%d/%y";
00099 #define TM_YEAR_BASE 1900
00100 #define __UNCONST(x) ((void *)(((const char *)(x) - (const char *)0) + (char *)0))
00101
00102 #endif
00103
00104
00105
00106
00107 #define ALT_E 0x01
00108 #define ALT_O 0x02
00109 #define LEGAL_ALT(x) { if (alt_format & ~(x)) return NULL; }
00110
00111
00112 static const u_char *conv_num(const unsigned char *, int *, uint, uint);
00113 static const u_char *find_string(const u_char *, int *, const char * const *,
00114 const char * const *, int);
00115
00116
00117 char *
00118 strptime(const char *buf, const char *fmt, struct tm *tm)
00119 {
00120 unsigned char c;
00121 const unsigned char *bp;
00122 int alt_format, i, split_year = 0;
00123 const char *new_fmt;
00124
00125 bp = (const u_char *)buf;
00126
00127 while (bp != NULL && (c = *fmt++) != '\0') {
00128
00129 alt_format = 0;
00130 i = 0;
00131
00132
00133 if (isspace(c)) {
00134 while (isspace(*bp))
00135 bp++;
00136 continue;
00137 }
00138
00139 if (c != '%')
00140 goto literal;
00141
00142
00143 again: switch (c = *fmt++) {
00144 case '%':
00145 literal:
00146 if (c != *bp++)
00147 return NULL;
00148 LEGAL_ALT(0);
00149 continue;
00150
00151
00152
00153
00154
00155 case 'E':
00156 LEGAL_ALT(0);
00157 alt_format |= ALT_E;
00158 goto again;
00159
00160 case 'O':
00161 LEGAL_ALT(0);
00162 alt_format |= ALT_O;
00163 goto again;
00164
00165
00166
00167
00168 case 'c':
00169 new_fmt = _ctloc(d_t_fmt);
00170 goto recurse;
00171
00172 case 'D':
00173 new_fmt = "%m/%d/%y";
00174 LEGAL_ALT(0);
00175 goto recurse;
00176
00177 case 'R':
00178 new_fmt = "%H:%M";
00179 LEGAL_ALT(0);
00180 goto recurse;
00181
00182 case 'r':
00183 new_fmt =_ctloc(t_fmt_ampm);
00184 LEGAL_ALT(0);
00185 goto recurse;
00186
00187 case 'T':
00188 new_fmt = "%H:%M:%S";
00189 LEGAL_ALT(0);
00190 goto recurse;
00191
00192 case 'X':
00193 new_fmt =_ctloc(t_fmt);
00194 goto recurse;
00195
00196 case 'x':
00197 new_fmt =_ctloc(d_fmt);
00198 recurse:
00199 bp = (const u_char *)strptime((const char *)bp,
00200 new_fmt, tm);
00201 LEGAL_ALT(ALT_E);
00202 continue;
00203
00204
00205
00206
00207 case 'A':
00208 case 'a':
00209 bp = find_string(bp, &tm->tm_wday, _ctloc(day),
00210 _ctloc(abday), 7);
00211 LEGAL_ALT(0);
00212 continue;
00213
00214 case 'B':
00215 case 'b':
00216 case 'h':
00217 bp = find_string(bp, &tm->tm_mon, _ctloc(mon),
00218 _ctloc(abmon), 12);
00219 LEGAL_ALT(0);
00220 continue;
00221
00222 case 'C':
00223 i = 20;
00224 bp = conv_num(bp, &i, 0, 99);
00225
00226 i = i * 100 - TM_YEAR_BASE;
00227 if (split_year)
00228 i += tm->tm_year % 100;
00229 split_year = 1;
00230 tm->tm_year = i;
00231 LEGAL_ALT(ALT_E);
00232 continue;
00233
00234 case 'd':
00235 case 'e':
00236 bp = conv_num(bp, &tm->tm_mday, 1, 31);
00237 LEGAL_ALT(ALT_O);
00238 continue;
00239
00240 case 'k':
00241 LEGAL_ALT(0);
00242
00243 case 'H':
00244 bp = conv_num(bp, &tm->tm_hour, 0, 23);
00245 LEGAL_ALT(ALT_O);
00246 continue;
00247
00248 case 'l':
00249 LEGAL_ALT(0);
00250
00251 case 'I':
00252 bp = conv_num(bp, &tm->tm_hour, 1, 12);
00253 if (tm->tm_hour == 12)
00254 tm->tm_hour = 0;
00255 LEGAL_ALT(ALT_O);
00256 continue;
00257
00258 case 'j':
00259 i = 1;
00260 bp = conv_num(bp, &i, 1, 366);
00261 tm->tm_yday = i - 1;
00262 LEGAL_ALT(0);
00263 continue;
00264
00265 case 'M':
00266 bp = conv_num(bp, &tm->tm_min, 0, 59);
00267 LEGAL_ALT(ALT_O);
00268 continue;
00269
00270 case 'm':
00271 i = 1;
00272 bp = conv_num(bp, &i, 1, 12);
00273 tm->tm_mon = i - 1;
00274 LEGAL_ALT(ALT_O);
00275 continue;
00276
00277 case 'p':
00278 bp = find_string(bp, &i, _ctloc(am_pm), NULL, 2);
00279 if (tm->tm_hour > 11)
00280 return NULL;
00281 tm->tm_hour += i * 12;
00282 LEGAL_ALT(0);
00283 continue;
00284
00285 case 'S':
00286 bp = conv_num(bp, &tm->tm_sec, 0, 61);
00287 LEGAL_ALT(ALT_O);
00288 continue;
00289
00290 case 'U':
00291 case 'W':
00292
00293
00294
00295
00296
00297
00298 bp = conv_num(bp, &i, 0, 53);
00299 LEGAL_ALT(ALT_O);
00300 continue;
00301
00302 case 'w':
00303 bp = conv_num(bp, &tm->tm_wday, 0, 6);
00304 LEGAL_ALT(ALT_O);
00305 continue;
00306
00307 case 'Y':
00308 i = TM_YEAR_BASE;
00309 bp = conv_num(bp, &i, 0, 9999);
00310 tm->tm_year = i - TM_YEAR_BASE;
00311 LEGAL_ALT(ALT_E);
00312 continue;
00313
00314 case 'y':
00315
00316 bp = conv_num(bp, &i, 0, 99);
00317
00318 if (split_year)
00319
00320 i += (tm->tm_year / 100) * 100;
00321 else {
00322 split_year = 1;
00323 if (i <= 68)
00324 i = i + 2000 - TM_YEAR_BASE;
00325 else
00326 i = i + 1900 - TM_YEAR_BASE;
00327 }
00328 tm->tm_year = i;
00329 continue;
00330
00331
00332
00333
00334 case 'n':
00335 case 't':
00336 while (isspace(*bp))
00337 bp++;
00338 LEGAL_ALT(0);
00339 continue;
00340
00341
00342 default:
00343 return NULL;
00344 }
00345 }
00346
00347 return __UNCONST(bp);
00348 }
00349
00350
00351 static const u_char *
00352 conv_num(const unsigned char *buf, int *dest, uint llim, uint ulim)
00353 {
00354 uint result = 0;
00355 unsigned char ch;
00356
00357
00358 uint rulim = ulim;
00359
00360 ch = *buf;
00361 if (ch < '0' || ch > '9')
00362 return NULL;
00363
00364 do {
00365 result *= 10;
00366 result += ch - '0';
00367 rulim /= 10;
00368 ch = *++buf;
00369 } while ((result * 10 <= ulim) && rulim && ch >= '0' && ch <= '9');
00370
00371 if (result < llim || result > ulim)
00372 return NULL;
00373
00374 *dest = result;
00375 return buf;
00376 }
00377
00378 static const u_char *
00379 find_string(const u_char *bp, int *tgt, const char * const *n1,
00380 const char * const *n2, int c)
00381 {
00382 int i;
00383 unsigned int len;
00384
00385
00386 for (; n1 != NULL; n1 = n2, n2 = NULL) {
00387 for (i = 0; i < c; i++, n1++) {
00388 len = strlen(*n1);
00389 if (strncasecmp(*n1, (const char *)bp, len) == 0) {
00390 *tgt = i;
00391 return bp + len;
00392 }
00393 }
00394 }
00395
00396
00397 return NULL;
00398 }