123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <langinfo.h>
- #include <time.h>
- #include <ctype.h>
- #include <stddef.h>
- #include <string.h>
- #include <strings.h>
- char *strptime(const char *s, const char *f, struct tm *tm)
- {
- int i, w, neg, adj, min, range, *dest;
- const char *ex;
- size_t len;
- while (*f) {
- if (*f != '%') {
- if (isspace(*f)) for (; *s && isspace(*s); s++);
- else if (*s != *f) return 0;
- else s++;
- f++;
- }
- f++;
- if (*f == '+') f++;
- if (isdigit(*f)) w=strtoul(f, (void *)&f, 10);
- else w=-1;
- adj=0;
- switch (*f++) {
- case 'a': case 'A':
- dest = &tm->tm_wday;
- min = ABDAY_1;
- range = 7;
- goto symbolic_range;
- case 'b': case 'B': case 'h':
- dest = &tm->tm_mon;
- min = ABMON_1;
- range = 12;
- goto symbolic_range;
- case 'c':
- s = strptime(s, nl_langinfo(D_T_FMT), tm);
- if (!s) return 0;
- break;
- case 'C':
- case 'd': case 'e':
- dest = &tm->tm_mday;
- min = 1;
- range = 31;
- goto numeric_range;
- case 'D':
- s = strptime(s, "%m/%d/%y", tm);
- if (!s) return 0;
- break;
- case 'H':
- dest = &tm->tm_hour;
- min = 0;
- range = 24;
- goto numeric_range;
- case 'I':
- dest = &tm->tm_hour;
- min = 1;
- range = 12;
- goto numeric_range;
- case 'j':
- dest = &tm->tm_yday;
- min = 1;
- range = 366;
- goto numeric_range;
- case 'm':
- dest = &tm->tm_mon;
- min = 1;
- range = 12;
- adj = 1;
- goto numeric_range;
- case 'M':
- dest = &tm->tm_min;
- min = 0;
- range = 60;
- goto numeric_range;
- case 'n': case 't':
- for (; *s && isspace(*s); s++);
- break;
- case 'p':
- ex = nl_langinfo(AM_STR);
- len = strlen(ex);
- if (!strncasecmp(s, ex, len)) {
- tm->tm_hour %= 12;
- break;
- }
- ex = nl_langinfo(PM_STR);
- len = strlen(ex);
- if (!strncasecmp(s, ex, len)) {
- tm->tm_hour %= 12;
- tm->tm_hour += 12;
- break;
- }
- return 0;
- case 'r':
- s = strptime(s, nl_langinfo(T_FMT_AMPM), tm);
- if (!s) return 0;
- break;
- case 'R':
- s = strptime(s, "%H:%M", tm);
- if (!s) return 0;
- break;
- case 'S':
- dest = &tm->tm_sec;
- min = 0;
- range = 61;
- goto numeric_range;
- case 'T':
- s = strptime(s, "%H:%M:%S", tm);
- if (!s) return 0;
- break;
- case 'U':
- case 'W':
- //FIXME
- return 0;
- case 'w':
- dest = &tm->tm_wday;
- min = 0;
- range = 7;
- goto numeric_range;
- case 'x':
- s = strptime(s, nl_langinfo(D_FMT), tm);
- if (!s) return 0;
- break;
- case 'X':
- s = strptime(s, nl_langinfo(T_FMT), tm);
- if (!s) return 0;
- break;
- case 'y':
- //FIXME
- return 0;
- case 'Y':
- dest = &tm->tm_year;
- if (w<0) w=4;
- adj = 1900;
- goto numeric_digits;
- case '%':
- if (*s++ != '%') return 0;
- break;
- numeric_range:
- if (!isdigit(*s)) return 0;
- *dest = 0;
- for (i=1; i<=min+range && isdigit(*s); i*=10)
- *dest = *dest * 10 + *s++ - '0';
- if (*dest - min >= (unsigned)range) return 0;
- *dest -= adj;
- switch((char *)dest - (char *)tm) {
- case offsetof(struct tm, tm_yday):
- ;
- }
- goto update;
- numeric_digits:
- neg = 0;
- if (*s == '+') s++;
- else if (*s == '-') neg=1, s++;
- if (!isdigit(*s)) return 0;
- for (*dest=i=0; i<w && isdigit(*s); i++)
- *dest = *dest * 10 + *s++ - '0';
- if (neg) *dest = -*dest;
- *dest -= adj;
- goto update;
- symbolic_range:
- for (i=2*range-1; i>=0; i--) {
- ex = nl_langinfo(min+i);
- len = strlen(ex);
- if (strncasecmp(s, ex, len)) continue;
- *dest = i % range;
- break;
- }
- if (i<0) return 0;
- goto update;
- update:
- //FIXME
- ;
- }
- }
- return (char *)s;
- }
|