📄 time.c
字号:
if (((i&128) + field_val) == 0) { /* mod 12? == 0 */ field_val = j; /* set to 12 */ } } field_val += (i & 1); if ((i & 8) && !field_val) { field_val += 7; } } if ((code & MASK_SPEC) == STRING_SPEC) { o_count = SIZE_MAX; field_val += spec[STRINGS_NL_ITEM_START + (code & 0xf)]; o = nl_langinfo(_NL_ITEM(LC_TIME, field_val)); } else { o_count = ((i >> 1) & 3) + 1; o = buf + o_count; do { *(char *)(--o) = '0' + (field_val % 10); field_val /= 10; } while (o > buf); if (*buf == '0') { *buf = ' ' + (i & 16); } } } OUTPUT: ++p; while (o_count && count && *o) { *s++ = *o++; --o_count; --count; } goto LOOP;}#endif/**********************************************************************/#ifdef L_strptime/* TODO: * 1) %l and %k are space-padded, so "%l" by itself fails while " %l" succeeds. * Both work for glibc. So, should we always strip spaces? * 2) %Z *//* Notes: * There are several differences between this strptime and glibc's strptime. * 1) glibc strips leading space before numeric conversions. * 2) glibc will read fields without whitespace in between. SUSv3 states * that you must have whitespace between conversion operators. Besides, * how do you know how long a number should be if there are leading 0s? * 3) glibc attempts to compute some the struct tm fields based on the * data retrieved; tm_wday in particular. I don't as I consider it * another glibc attempt at mind-reading... */#define NO_E_MOD 0x80#define NO_O_MOD 0x40#define ILLEGAL_SPEC 0x3f#define INT_SPEC 0x00 /* must be 0x00!! */#define STRING_SPEC 0x10 /* must be 0x10!! */#define CALC_SPEC 0x20#define STACKED_SPEC 0x30#define MASK_SPEC 0x30/* Warning: Assumes ASCII values! (as do lots of other things in the lib...) */static const unsigned char spec[] = { /* A */ 0x02 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* B */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* C */ 0x08 | INT_SPEC | NO_O_MOD, /* D */ 0x01 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* E */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* F */ 0x02 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ /* G */ 0x0f | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ /* H */ 0x06 | INT_SPEC | NO_E_MOD, /* I */ 0x07 | INT_SPEC | NO_E_MOD, /* J */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* K */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* L */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* M */ 0x04 | INT_SPEC | NO_E_MOD, /* N */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* O */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* P */ 0x00 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ /* Q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* R */ 0x03 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* S */ 0x05 | INT_SPEC | NO_E_MOD, /* T */ 0x04 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* U */ 0x0c | INT_SPEC | NO_E_MOD, /* V */ 0x0d | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ /* W */ 0x0c | INT_SPEC | NO_E_MOD, /* X */ 0x0a | STACKED_SPEC | NO_O_MOD, /* Y */ 0x0a | INT_SPEC | NO_O_MOD, /* Z */ 0x02 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ /* WARNING! This assumes orderings: * AM,PM * ABDAY_1-ABDAY-7,DAY_1-DAY_7 * ABMON_1-ABMON_12,MON_1-MON12 * Also, there are exactly 6 bytes between 'Z' and 'a'. */#define STRINGS_NL_ITEM_START (26) _NL_ITEM_INDEX(AM_STR), /* p (P) */ _NL_ITEM_INDEX(ABMON_1), /* B, b */ _NL_ITEM_INDEX(ABDAY_1), /* A, a */ 2, 24, 14, /* a */ 0x02 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* b */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* c */ 0x08 | STACKED_SPEC | NO_O_MOD, /* d */ 0x00 | INT_SPEC | NO_E_MOD, /* e */ 0x00 | INT_SPEC | NO_E_MOD, /* f */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* g */ 0x0e | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ /* h */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* i */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* j */ 0x01 | INT_SPEC | NO_E_MOD | NO_O_MOD, /* k */ 0x06 | INT_SPEC | NO_E_MOD, /* glibc */ /* l */ 0x07 | INT_SPEC | NO_E_MOD, /* glibc */ /* m */ 0x02 | INT_SPEC | NO_E_MOD, /* n */ 0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* o */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* p */ 0x00 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* r */ 0x0b | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* s */ 0x00 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ /* t */ 0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* u */ 0x0b | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ /* v */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* w */ 0x03 | INT_SPEC | NO_E_MOD, /* x */ 0x09 | STACKED_SPEC | NO_O_MOD, /* y */ 0x09 | INT_SPEC, /* z */ 0x01 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */#define INT_FIELD_START (26+6+26) /* (field #) << 3 + lower bound (0|1) + correction 0:none, 2:-1, 4:-1900 * followed by upper bound prior to correction with 1=>366 and 2=>9999. */ /* d, e */ (3 << 3) + 1 + 0, 31, /* j */ (7 << 3) + 1 + 2, /* 366 */ 1, /* m */ (4 << 3) + 1 + 2, 12, /* w */ (6 << 3) + 0 + 0, 6, /* M */ (1 << 3) + 0 + 0, 59, /* S */ 0 + 0 + 0, 60, /* H (k) */ (2 << 3) + 0 + 0, 23, /* I (l) */ (9 << 3) + 1 + 0, 12, /* goes with 8 -- am/pm */ /* C */ (10<< 3) + 0 + 0, 99, /* y */ (11<< 3) + 0 + 0, 99, /* Y */ (5 << 3) + 0 + 4, /* 9999 */ 2, /* u */ (6 << 3) + 1 + 0, 7, /* The following are processed and range-checked, but ignored otherwise. */ /* U, W */ (12<< 3) + 0 + 0, 53, /* V */ (12<< 3) + 1 + 0, 53, /* g */ (12<< 3) + 0 + 0, 99, /* G */ (12<< 3) + 0 /*+ 4*/, /* 9999 */ 2, /* Note: -1 or 10000? */#define STACKED_STRINGS_START (INT_FIELD_START+32) 5, 6, 14, 22, 27, /* 5 - offsets from offset-count to strings */ ' ', 0, /* 2 - %n or %t */ '%', 'm', '/', '%', 'd', '/', '%', 'y', 0, /* 9 - %D */ '%', 'Y', '-', '%', 'm', '-', '%', 'd', 0, /* 9 - %F (glibc extension) */ '%', 'H', ':', '%', 'M', 0, /* 6 - %R*/ '%', 'H', ':', '%', 'M', ':', '%', 'S', 0, /* 9 - %T */#define STACKED_STRINGS_NL_ITEM_START (STACKED_STRINGS_START + 40) _NL_ITEM_INDEX(D_T_FMT), /* c */ _NL_ITEM_INDEX(D_FMT), /* x */ _NL_ITEM_INDEX(T_FMT), /* X */ _NL_ITEM_INDEX(T_FMT_AMPM), /* r */#ifdef ENABLE_ERA_CODE _NL_ITEM_INDEX(ERA_D_T_FMT), /* Ec */ _NL_ITEM_INDEX(ERA_D_FMT), /* Ex */ _NL_ITEM_INDEX(ERA_T_FMT), /* EX */#endif};#define MAX_PUSH 4char *strptime(const char *__restrict buf, const char *__restrict format, struct tm *__restrict tm){ register const char *p; char *o; const char *stack[MAX_PUSH]; int i, j, lvl; int fields[13]; unsigned char mod; unsigned char code; i = 0; do { fields[i] = INT_MIN; } while (++i < 13); lvl = 0; p = format; LOOP: if (!*p) { if (lvl == 0) { /* Done. */ if (fields[6] == 7) { /* Cleanup for %u here since just once. */ fields[6] = 0; /* Don't use mod in case unset. */ } i = 0; do { /* Store the values into tm. */ ((int *) tm)[i] = fields[i]; } while (++i < 8); return (char *) buf; /* Success. */ } p = stack[--lvl]; goto LOOP; } if ((*p == '%') && (*++p != '%')) { mod = ILLEGAL_SPEC; if ((*p == 'O') || (*p == 'E')) { /* Modifier? */ mod |= ((*p == 'O') ? NO_O_MOD : NO_E_MOD); ++p; } if (!*p || (((unsigned char)(((*p) | 0x20) - 'a')) >= 26) || (((code = spec[(int)(*p - 'A')]) & mod) >= ILLEGAL_SPEC) ) { return NULL; /* Illegal spec. */ } if ((code & MASK_SPEC) == STACKED_SPEC) { if (lvl == MAX_PUSH) { return NULL; /* Stack full so treat as illegal spec. */ } stack[lvl++] = ++p; if ((code &= 0xf) < 8) { p = ((const char *) spec) + STACKED_STRINGS_START + code; p += *((unsigned char *)p); goto LOOP; } p = ((const char *) spec) + STACKED_STRINGS_NL_ITEM_START + (code & 7);#ifdef ENABLE_ERA_CODE if ((mod & NO_E_MOD) /* Actually, this means E modifier present. */ && (*(o = nl_langinfo(_NL_ITEM(LC_TIME, (int)(((unsigned char *)p)[4])) ))) ) { p = o; goto LOOP; }#endif p = nl_langinfo(_NL_ITEM(LC_TIME, (int)(*((unsigned char *)p)))); goto LOOP; } ++p; if ((code & MASK_SPEC) == STRING_SPEC) { code &= 0xf; j = spec[STRINGS_NL_ITEM_START + 3 + code]; i = _NL_ITEM(LC_TIME, spec[STRINGS_NL_ITEM_START + code]); /* Go backwards to check full names before abreviations. */ do { --j; o = nl_langinfo(i+j); if (!strncasecmp(buf,o,strlen(o)) && *o) { /* Found a match. */ do { ++buf; } while (*++o); if (!code) { /* am/pm */ fields[8] = j * 12; if (fields[9] >= 0) { /* We have a previous %I or %l. */ fields[2] = fields[9] + fields[8]; } } else { /* day (4) or month (6) */ fields[2 + (code << 1)] = j % (spec[STRINGS_NL_ITEM_START + 3 + code] >> 1); } goto LOOP; } } while (j); return NULL; /* Failed to match. */ } if ((code & MASK_SPEC) == CALC_SPEC) { if ((code &= 0xf) < 1) { /* s or z*/ time_t t; o = (char *) buf; i = errno; __set_errno(0); if (!isspace(*buf)) { /* Signal an error if whitespace. */#ifdef TIME_T_IS_UNSIGNED t = strtoul(buf, &o, 10);#else t = strtol(buf, &o, 10);#endif } if ((o == buf) || errno) { /* Not a number or overflow. */ return NULL; } __set_errno(i); /* Restore errno. */ buf = o; if (!code) { /* s */ localtime_r(&t, tm); /* TODO: check for failure? */ i = 0; do { /* Now copy values from tm to fields. */ fields[i] = ((int *) tm)[i]; } while (++i < 8); } } /* TODO: glibc treats %Z as a nop. For now, do the same. */ goto LOOP; } assert((code & MASK_SPEC) == INT_SPEC); { register const unsigned char *x; code &= 0xf; x = spec + INT_FIELD_START + (code << 1); if ((j = x[1]) < 3) { /* upper bound (inclusive) */ j = ((j==1) ? 366 : 9999); } i = -1; while (isdigit(*buf)) { if (i < 0) { i = 0; } if ((i = 10*i + (*buf - '0')) > j) { /* Overflow. */ return NULL; } ++buf; } if (i < (*x & 1)) { /* This catches no-digit case too. */ return NULL; } if (*x & 2) { --i; } if (*x & 4) { i -= 1900; } if (*x == (9 << 3) + 1 + 0) { /* %I or %l */ if (i == 12) { i = 0; } if (fields[8] >= 0) { /* We have a previous %p or %P. */ fields[2] = i + fields[8]; } } fields[(*x) >> 3] = i; if (((unsigned char)(*x - (10<< 3) + 0 + 0)) <= 8) { /* %C or %y */ if ((j = fields[10]) < 0) { /* No %C, so i must be %y data. */ if (i <= 68) { /* Map [0-68] to 2000+i */ i += 100; } } else { /* Have %C data, but what about %y? */ if ((i = fields[11]) < 0) { /* No %y data. */ i = 0; /* Treat %y val as 0 following glibc's example. */ } i += 100*(j - 19); } fields[5] = i; } } goto LOOP; } else if (isspace(*p)) { ++p; while (isspace(*buf)) { ++buf; } goto LOOP; } else if (*buf++ == *p++) { goto LOOP; } return NULL;}#endif/**********************************************************************/#ifdef L_time#ifndef __BCC__#error The uClibc version of time is in sysdeps/linux/common.#endiftime_t time(register time_t *tloc){ struct timeval tv; register struct timeval *p = &tv; gettimeofday(p, NULL); /* This should never fail... */ if (tloc) { *tloc = p->tv_sec; } return p->tv_sec;}#endif/**********************************************************************/#ifdef L_tzsetstatic const char vals[] = { 'T', 'Z', 0, /* 3 */ 'U', 'T', 'C', 0, /* 4 */ 25, 60, 60, 1, /* 4 */ '.', 1, /* M */ 5, '.', 1, 6, 0, 0, /* Note: overloaded for non-M non-J case... */ 0, 1, 0, /* J */ ',', 'M', '4', '.', '1', '.', '0', ',', 'M', '1', '0', '.', '5', '.', '0', 0};#define TZ vals#define UTC (vals + 3)#define RANGE (vals + 7)#define RULE (vals + 11 - 1)#define DEFAULT_RULES (vals + 22)/* Initialize to UTC. */int daylight = 0;long timezone = 0;char *tzname[2] = { (char *) UTC, (char *) (UTC-1) };#ifdef __UCLIBC_HAS_THREADS__pthread_mutex_t _time_tzlock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;#endifrule_struct _time_tzinfo[2];static const char *getoffset(register const char *e, long *pn){ register const char *s = RANGE-1; long n; int f; n = 0; f = -1; do { ++s; if (isdigit(*e)) { f = *e++ - '0'; } if (isdigit(*e)) { f = 10 * f + (*e++ - '0'); } if (((unsigned int)f) >= *s) { return NULL; } n = (*s) * n + f; f = 0; if (*e == ':') { ++e; --f; } } while (*s > 1); *pn = n; return e;}static const char *getnumber(register const char *e, int *pn){#ifdef __BCC__ /* bcc can optimize the counter if it thinks it is a pointer... */ register const char *n = (const char *) 3; int f; f = 0; while (n && isdigit(*e)) { f = 10 * f + (*e++ - '0'); --n; } *pn = f; return (n == (const char *) 3) ? NULL : e;#else /* __BCC__ */ int n, f; n = 3; f = 0; while (n && isdigit(*e)) { f = 10 * f + (*e++ - '0'); --n; } *pn = f; return (n == 3) ? NULL : e;#endif /* __BCC__ */}#ifdef __TIME_TZ_FILE#ifdef __TIME_TZ_FILE_ONCEstatic int TZ_file_read; /* Let BSS initialization set this to 0. */#endif /* __TIME_TZ_FILE_ONCE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -