github.com/afumu/libc@v0.0.6/musl/src/time/strptime.c (about) 1 #include <stdlib.h> 2 #include <langinfo.h> 3 #include <time.h> 4 #include <ctype.h> 5 #include <stddef.h> 6 #include <string.h> 7 #include <strings.h> 8 9 char *strptime(const char *restrict s, const char *restrict f, struct tm *restrict tm) 10 { 11 int i, w, neg, adj, min, range, *dest, dummy; 12 const char *ex; 13 size_t len; 14 int want_century = 0, century = 0, relyear = 0; 15 while (*f) { 16 if (*f != '%') { 17 if (isspace(*f)) for (; *s && isspace(*s); s++); 18 else if (*s != *f) return 0; 19 else s++; 20 f++; 21 continue; 22 } 23 f++; 24 if (*f == '+') f++; 25 if (isdigit(*f)) { 26 char *new_f; 27 w=strtoul(f, &new_f, 10); 28 f = new_f; 29 } else { 30 w=-1; 31 } 32 adj=0; 33 switch (*f++) { 34 case 'a': case 'A': 35 dest = &tm->tm_wday; 36 min = ABDAY_1; 37 range = 7; 38 goto symbolic_range; 39 case 'b': case 'B': case 'h': 40 dest = &tm->tm_mon; 41 min = ABMON_1; 42 range = 12; 43 goto symbolic_range; 44 case 'c': 45 s = strptime(s, nl_langinfo(D_T_FMT), tm); 46 if (!s) return 0; 47 break; 48 case 'C': 49 dest = ¢ury; 50 if (w<0) w=2; 51 want_century |= 2; 52 goto numeric_digits; 53 case 'd': case 'e': 54 dest = &tm->tm_mday; 55 min = 1; 56 range = 31; 57 goto numeric_range; 58 case 'D': 59 s = strptime(s, "%m/%d/%y", tm); 60 if (!s) return 0; 61 break; 62 case 'H': 63 dest = &tm->tm_hour; 64 min = 0; 65 range = 24; 66 goto numeric_range; 67 case 'I': 68 dest = &tm->tm_hour; 69 min = 1; 70 range = 12; 71 goto numeric_range; 72 case 'j': 73 dest = &tm->tm_yday; 74 min = 1; 75 range = 366; 76 adj = 1; 77 goto numeric_range; 78 case 'm': 79 dest = &tm->tm_mon; 80 min = 1; 81 range = 12; 82 adj = 1; 83 goto numeric_range; 84 case 'M': 85 dest = &tm->tm_min; 86 min = 0; 87 range = 60; 88 goto numeric_range; 89 case 'n': case 't': 90 for (; *s && isspace(*s); s++); 91 break; 92 case 'p': 93 ex = nl_langinfo(AM_STR); 94 len = strlen(ex); 95 if (!strncasecmp(s, ex, len)) { 96 tm->tm_hour %= 12; 97 s += len; 98 break; 99 } 100 ex = nl_langinfo(PM_STR); 101 len = strlen(ex); 102 if (!strncasecmp(s, ex, len)) { 103 tm->tm_hour %= 12; 104 tm->tm_hour += 12; 105 s += len; 106 break; 107 } 108 return 0; 109 case 'r': 110 s = strptime(s, nl_langinfo(T_FMT_AMPM), tm); 111 if (!s) return 0; 112 break; 113 case 'R': 114 s = strptime(s, "%H:%M", tm); 115 if (!s) return 0; 116 break; 117 case 'S': 118 dest = &tm->tm_sec; 119 min = 0; 120 range = 61; 121 goto numeric_range; 122 case 'T': 123 s = strptime(s, "%H:%M:%S", tm); 124 if (!s) return 0; 125 break; 126 case 'U': 127 case 'W': 128 /* Throw away result, for now. (FIXME?) */ 129 dest = &dummy; 130 min = 0; 131 range = 54; 132 goto numeric_range; 133 case 'w': 134 dest = &tm->tm_wday; 135 min = 0; 136 range = 7; 137 goto numeric_range; 138 case 'x': 139 s = strptime(s, nl_langinfo(D_FMT), tm); 140 if (!s) return 0; 141 break; 142 case 'X': 143 s = strptime(s, nl_langinfo(T_FMT), tm); 144 if (!s) return 0; 145 break; 146 case 'y': 147 dest = &relyear; 148 w = 2; 149 want_century |= 1; 150 goto numeric_digits; 151 case 'Y': 152 dest = &tm->tm_year; 153 if (w<0) w=4; 154 adj = 1900; 155 want_century = 0; 156 goto numeric_digits; 157 case '%': 158 if (*s++ != '%') return 0; 159 break; 160 default: 161 return 0; 162 numeric_range: 163 if (!isdigit(*s)) return 0; 164 *dest = 0; 165 for (i=1; i<=min+range && isdigit(*s); i*=10) 166 *dest = *dest * 10 + *s++ - '0'; 167 if (*dest - min >= (unsigned)range) return 0; 168 *dest -= adj; 169 switch((char *)dest - (char *)tm) { 170 case offsetof(struct tm, tm_yday): 171 ; 172 } 173 goto update; 174 numeric_digits: 175 neg = 0; 176 if (*s == '+') s++; 177 else if (*s == '-') neg=1, s++; 178 if (!isdigit(*s)) return 0; 179 for (*dest=i=0; i<w && isdigit(*s); i++) 180 *dest = *dest * 10 + *s++ - '0'; 181 if (neg) *dest = -*dest; 182 *dest -= adj; 183 goto update; 184 symbolic_range: 185 for (i=2*range-1; i>=0; i--) { 186 ex = nl_langinfo(min+i); 187 len = strlen(ex); 188 if (strncasecmp(s, ex, len)) continue; 189 s += len; 190 *dest = i % range; 191 break; 192 } 193 if (i<0) return 0; 194 goto update; 195 update: 196 //FIXME 197 ; 198 } 199 } 200 if (want_century) { 201 tm->tm_year = relyear; 202 if (want_century & 2) tm->tm_year += century * 100 - 1900; 203 else if (tm->tm_year <= 68) tm->tm_year += 100; 204 } 205 return (char *)s; 206 }