diff options
author | 2005-07-05 13:40:51 +0000 | |
---|---|---|
committer | 2005-07-05 13:40:51 +0000 | |
commit | 3f56448e55c7291e472b8329d4adc9f24f811218 (patch) | |
tree | 7b3382971fe172139482fec8d86122539a88ad87 /lib/libc/time/strftime.c | |
parent | protect against cvs_getln() failure. (diff) | |
download | wireguard-openbsd-3f56448e55c7291e472b8329d4adc9f24f811218.tar.xz wireguard-openbsd-3f56448e55c7291e472b8329d4adc9f24f811218.zip |
Update to tzcode2005j.
Diffstat (limited to 'lib/libc/time/strftime.c')
-rw-r--r-- | lib/libc/time/strftime.c | 128 |
1 files changed, 74 insertions, 54 deletions
diff --git a/lib/libc/time/strftime.c b/lib/libc/time/strftime.c index 8246302c69d..cfa345569f9 100644 --- a/lib/libc/time/strftime.c +++ b/lib/libc/time/strftime.c @@ -1,12 +1,6 @@ -/* -** XXX To do: figure out correct (as distinct from standard-mandated) -** output for "two digits of year" and "century" formats when -** the year is negative or less than 100. --ado, 2004-09-09 -*/ - #if defined(LIBC_SCCS) && !defined(lint) && !defined(NOID) -static char elsieid[] = "@(#)strftime.c 7.64"; -static char *rcsid = "$OpenBSD: strftime.c,v 1.14 2004/10/18 22:33:43 millert Exp $"; +static char elsieid[] = "@(#)strftime.c 7.75"; +static char *rcsid = "$OpenBSD: strftime.c,v 1.15 2005/07/05 13:40:51 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include "private.h" @@ -109,7 +103,7 @@ static const struct lc_time_T C_time_locale = { ** C99 requires this format. ** Previously this code used "%D %X", but we now conform to C99. ** Note that - ** "%a %b %d %H:%M:%S %Y" + ** "%a %b %d %H:%M:%S %Y" ** is used by Solaris 2.3. */ "%a %b %e %T %Y", @@ -126,10 +120,9 @@ static const struct lc_time_T C_time_locale = { static char * _add P((const char *, char *, const char *)); static char * _conv P((int, const char *, char *, const char *)); -static char * _lconv P((long, const char *, char *, const char *)); -static char * _fmt P((const char *, const struct tm *, char *, const char *, int *)); - -size_t strftime P((char *, size_t, const char *, const struct tm *)); +static char * _fmt P((const char *, const struct tm *, char *, const char *, + int *)); +static char * _yconv P((int, int, int, int, char *, const char *)); extern char * tzname[]; @@ -137,7 +130,6 @@ extern char * tzname[]; #define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS" #endif /* !defined YEAR_2000_NAME */ - #define IN_NONE 0 #define IN_SOME 1 #define IN_THIS 2 @@ -232,9 +224,8 @@ label: ** something completely different. ** (ado, 1993-05-24) */ - pt = _conv((int) ((t->tm_year + - (long) TM_YEAR_BASE) / 100), - "%02d", pt, ptlim); + pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0, + pt, ptlim); continue; case 'c': { @@ -289,7 +280,7 @@ label: ** t->tm_hour % 12 : 12, 2, ' '); ** ...and has been changed to the below to ** match SunOS 4.1.1 and Arnold Robbins' - ** strftime version 3.0. That is, "%k" and + ** strftime version 3.0. That is, "%k" and ** "%l" have been swapped. ** (ado, 1993-05-24) */ @@ -309,7 +300,7 @@ label: ** _conv(t->tm_hour, 2, ' '); ** ...and has been changed to the below to ** match SunOS 4.1.1 and Arnold Robbin's - ** strftime version 3.0. That is, "%k" and + ** strftime version 3.0. That is, "%k" and ** "%l" have been swapped. ** (ado, 1993-05-24) */ @@ -384,7 +375,7 @@ label: case 'G': /* ISO 8601 year (four digits) */ case 'g': /* ISO 8601 year (two digits) */ /* -** From Arnold Robbins' strftime version 3.0: "the week number of the +** From Arnold Robbins' strftime version 3.0: "the week number of the ** year (the first Monday as the first day of week 1) as a decimal number ** (01-53)." ** (ado, 1993-05-24) @@ -397,18 +388,19 @@ label: ** might also contain days from the previous year and the week before week ** 01 of a year is the last week (52 or 53) of the previous year even if ** it contains days from the new year. A week starts with Monday (day 1) -** and ends with Sunday (day 7). For example, the first week of the year +** and ends with Sunday (day 7). For example, the first week of the year ** 1997 lasts from 1996-12-30 to 1997-01-05..." ** (ado, 1996-01-02) */ { - long year; + int year; + int base; int yday; int wday; int w; year = t->tm_year; - year += TM_YEAR_BASE; + base = TM_YEAR_BASE; yday = t->tm_yday; wday = t->tm_wday; for ( ; ; ) { @@ -416,7 +408,7 @@ label: int bot; int top; - len = isleap(year) ? + len = isleap_sum(year, base) ? DAYSPERLYEAR : DAYSPERNYEAR; /* @@ -435,7 +427,7 @@ label: top += DAYSPERWEEK; top += len; if (yday >= top) { - ++year; + ++base; w = 1; break; } @@ -444,8 +436,8 @@ label: DAYSPERWEEK); break; } - --year; - yday += isleap(year) ? + --base; + yday += isleap_sum(year, base) ? DAYSPERLYEAR : DAYSPERNYEAR; } @@ -461,9 +453,9 @@ label: pt, ptlim); else if (*format == 'g') { *warnp = IN_ALL; - pt = _conv((int) (year % 100), - "%02d", pt, ptlim); - } else pt = _lconv(year, "%04ld", + pt = _yconv(year, base, 0, 1, + pt, ptlim); + } else pt = _yconv(year, base, 1, 1, pt, ptlim); } continue; @@ -501,13 +493,12 @@ label: continue; case 'y': *warnp = IN_ALL; - pt = _conv((int) ((t->tm_year + - (long) TM_YEAR_BASE) % 100), - "%02d", pt, ptlim); + pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1, + pt, ptlim); continue; case 'Y': - pt = _lconv(t->tm_year + (long) TM_YEAR_BASE, - "%04ld", pt, ptlim); + pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1, + pt, ptlim); continue; case 'Z': #ifdef TM_ZONE @@ -537,12 +528,12 @@ label: /* ** C99 says that the UTC offset must ** be computed by looking only at - ** tm_isdst. This requirement is + ** tm_isdst. This requirement is ** incorrect, since it means the code ** must rely on magic (in this case ** altzone and timezone), and the ** magic might not have the correct - ** offset. Doing things correctly is + ** offset. Doing things correctly is ** tricky and requires disobeying C99; ** see GNU C strftime for details. ** For now, punt and conform to the @@ -571,9 +562,10 @@ label: diff = -diff; } else sign = "+"; pt = _add(sign, pt, ptlim); - diff /= 60; - pt = _conv((diff/60)*100 + diff%60, - "%04d", pt, ptlim); + diff /= SECSPERMIN; + diff = (diff / MINSPERHOUR) * 100 + + (diff % MINSPERHOUR); + pt = _conv(diff, "%04d", pt, ptlim); } continue; case '+': @@ -583,7 +575,7 @@ label: case '%': /* ** X311J/88-090 (4.12.3.5): if conversion char is - ** undefined, behavior is undefined. Print out the + ** undefined, behavior is undefined. Print out the ** character itself as printf(3) also does. */ default: @@ -611,26 +603,54 @@ const char * const ptlim; } static char * -_lconv(n, format, pt, ptlim) -const long n; -const char * const format; -char * const pt; +_add(str, pt, ptlim) +const char * str; +char * pt; const char * const ptlim; { - char buf[INT_STRLEN_MAXIMUM(long) + 1]; - - (void) snprintf(buf, sizeof buf, format, n); - return _add(buf, pt, ptlim); + while (pt < ptlim && (*pt = *str++) != '\0') + ++pt; + return pt; } +/* +** POSIX and the C Standard are unclear or inconsistent about +** what %C and %y do if the year is negative or exceeds 9999. +** Use the convention that %C concatenated with %y yields the +** same output as %Y, and that %Y contains at least 4 bytes, +** with more only if necessary. +*/ + static char * -_add(str, pt, ptlim) -const char * str; +_yconv(a, b, convert_top, convert_yy, pt, ptlim) +const int a; +const int b; +const int convert_top; +const int convert_yy; char * pt; const char * const ptlim; { - while (pt < ptlim && (*pt = *str++) != '\0') - ++pt; + register int lead; + register int trail; + +#define DIVISOR 100 + trail = a % DIVISOR + b % DIVISOR; + lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR; + trail %= DIVISOR; + if (trail < 0 && lead > 0) { + trail += DIVISOR; + --lead; + } else if (lead < 0 && trail > 0) { + trail -= DIVISOR; + ++lead; + } + if (convert_top) { + if (lead == 0 && trail < 0) + pt = _add("-0", pt, ptlim); + else pt = _conv(lead, "%02d", pt, ptlim); + } + if (convert_yy) + pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim); return pt; } @@ -679,7 +699,7 @@ _loc P((void)) ** Slurp the locale file into the cache. */ namesize = strlen(name) + 1; - if (sizeof filename < + if (sizeof filename < ((sizeof locale_home) + namesize + (sizeof lc_time))) goto no_locale; oldsun = 0; |