proposed changes to strftime.c
Paul Eggert
eggert at twinsun.com
Tue May 25 18:33:13 UTC 1993
Here are some proposed changes to strftime.c:
Use ISO standard date format for %x; this is more appropriate than the
American date format, which confuses non-Americans. Especially for
dates like 01/02/03; the ISO date 2003-01-02 is much clearer for
everybody, and it sorts correctly too.
_conv fails when n is negative, and it's hard to get it exactly right
when n is INT_MIN. Why not let sprintf do the work?
The buffer inside _conv might overflow with 64-bit ints.
Use `const' when possible, so that the data can be shared in the
read-only text segment.
Use function prototypes when possible, to keep lint checkers happy.
There's a /* in a comment just before `You are understood not to
expect this.'
Here's a patch.
*** draft-strftime.c Tue May 25 10:39:33 1993
--- draft-strftime1.c Tue May 25 11:28:38 1993
***************
*** 1,6 ****
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)strftime.c 7.4";
/*
** Based on the UCB version whose ID appears below.
** This is ANSIish only when time is treated identically in all locales and
--- 1,6 ----
#ifndef lint
#ifndef NOID
! static const char elsieid[] = "@(#)strftime.c 7.4";
/*
** Based on the UCB version whose ID appears below.
** This is ANSIish only when time is treated identically in all locales and
***************
*** 26,64 ****
*/
#if defined(LIBC_SCCS) && !defined(lint)
! static char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
#endif /* LIBC_SCCS and not lint */
! #include "sys/types.h"
! #include "time.h"
#include "tzfile.h"
! static char *afmt[] = {
! "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
};
! static char *Afmt[] = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
! "Saturday",
};
! static char *bfmt[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
! "Oct", "Nov", "Dec",
};
! static char *Bfmt[] = {
"January", "February", "March", "April", "May", "June", "July",
! "August", "September", "October", "November", "December",
};
! static char *_add();
! static char *_conv();
! static char *_fmt();
size_t
strftime(s, maxsize, format, t)
char *s;
size_t maxsize;
! char *format;
! struct tm *t;
{
size_t gsize;
--- 26,65 ----
*/
#if defined(LIBC_SCCS) && !defined(lint)
! static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
#endif /* LIBC_SCCS and not lint */
! #include "private.h"
#include "tzfile.h"
! static const char * const afmt[] = {
! "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
! static const char * const Afmt[] = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
! "Saturday"
};
! static const char * const bfmt[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
! "Oct", "Nov", "Dec"
};
! static const char * const Bfmt[] = {
"January", "February", "March", "April", "May", "June", "July",
! "August", "September", "October", "November", "December"
};
! static char *_add P((const char *, size_t *, char *));
! static char *_conv P((int, const char *, size_t *, char *));
! static char *_fmt P((const char *, const struct tm *, size_t *, char *));
+ size_t strftime P((char *, size_t, const char *, const struct tm *));
+
size_t
strftime(s, maxsize, format, t)
char *s;
size_t maxsize;
! const char *format;
! const struct tm *t;
{
size_t gsize;
***************
*** 72,79 ****
static char *
_fmt(format, t, gsizep, pt)
! char *format;
! struct tm *t;
size_t *gsizep;
char *pt;
{
--- 73,80 ----
static char *
_fmt(format, t, gsizep, pt)
! const char *format;
! const struct tm *t;
size_t *gsizep;
char *pt;
{
***************
*** 113,119 ****
** (ado, 5/24/93)
*/
pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
! 2, '0', gsizep, pt);
continue;
case 'D':
case 'x':
--- 114,120 ----
** (ado, 5/24/93)
*/
pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
! "%02d", gsizep, pt);
continue;
case 'D':
case 'x':
***************
*** 126,137 ****
** standard calls for "date, using locale's
** date format," anything goes. Using just
** numbers (as here) makes Quakers happier.
! ** (ado, 5/24/93)
*/
! pt = _fmt("%m/%d/%y", t, gsizep, pt);
continue;
case 'd':
! pt = _conv(t->tm_mday, 2, '0', gsizep, pt);
continue;
case 'E':
case 'O':
--- 127,138 ----
** standard calls for "date, using locale's
** date format," anything goes. Using just
** numbers (as here) makes Quakers happier.
! ** This is the ISO standard date format.
*/
! pt = _fmt("%Y-%m-%d", t, gsizep, pt);
continue;
case 'd':
! pt = _conv(t->tm_mday, "%02d", gsizep, pt);
continue;
case 'E':
case 'O':
***************
*** 148,165 ****
*/
goto label;
case 'e':
! pt = _conv(t->tm_mday, 2, ' ', gsizep, pt);
continue;
case 'H':
! pt = _conv(t->tm_hour, 2, '0', gsizep, pt);
continue;
case 'I':
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
! 2, '0', gsizep, pt);
continue;
case 'j':
! pt = _conv(t->tm_yday + 1, 3, '0', gsizep, pt);
continue;
case 'k':
/*
--- 149,166 ----
*/
goto label;
case 'e':
! pt = _conv(t->tm_mday, "%2d", gsizep, pt);
continue;
case 'H':
! pt = _conv(t->tm_hour, "%02d", gsizep, pt);
continue;
case 'I':
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
! "%02d", gsizep, pt);
continue;
case 'j':
! pt = _conv(t->tm_yday + 1, "%03d", gsizep, pt);
continue;
case 'k':
/*
***************
*** 172,178 ****
** "%l" have been swapped.
** (ado, 5/24/93)
*/
! pt = _conv(t->tm_hour, 2, ' ', gsizep, pt);
continue;
#ifdef KITCHEN_SINK
case 'K':
--- 173,179 ----
** "%l" have been swapped.
** (ado, 5/24/93)
*/
! pt = _conv(t->tm_hour, "%2d", gsizep, pt);
continue;
#ifdef KITCHEN_SINK
case 'K':
***************
*** 194,206 ****
*/
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
! 2, ' ', gsizep, pt);
continue;
case 'M':
! pt = _conv(t->tm_min, 2, '0', gsizep, pt);
continue;
case 'm':
! pt = _conv(t->tm_mon + 1, 2, '0', gsizep, pt);
continue;
case 'n':
pt = _add("\n", gsizep, pt);
--- 195,207 ----
*/
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
! "%2d", gsizep, pt);
continue;
case 'M':
! pt = _conv(t->tm_min, "%02d", gsizep, pt);
continue;
case 'm':
! pt = _conv(t->tm_mon + 1, "%02d", gsizep, pt);
continue;
case 'n':
pt = _add("\n", gsizep, pt);
***************
*** 216,222 ****
pt = _fmt("%I:%M:%S %p", t, gsizep, pt);
continue;
case 'S':
! pt = _conv(t->tm_sec, 2, '0', gsizep, pt);
continue;
case 'T':
case 'X':
--- 217,223 ----
pt = _fmt("%I:%M:%S %p", t, gsizep, pt);
continue;
case 'S':
! pt = _conv(t->tm_sec, "%02d", gsizep, pt);
continue;
case 'T':
case 'X':
***************
*** 227,233 ****
continue;
case 'U':
pt = _conv((t->tm_yday + 7 - t->tm_wday) / 7,
! 2, '0', gsizep, pt);
continue;
case 'u':
/*
--- 228,234 ----
continue;
case 'U':
pt = _conv((t->tm_yday + 7 - t->tm_wday) / 7,
! "%02d", gsizep, pt);
continue;
case 'u':
/*
***************
*** 237,243 ****
** (ado, 5/24/93)
*/
pt = _conv((t->tm_wday == 0) ? 7 : t->tm_wday,
! 1, '0', gsizep, pt);
continue;
case 'V':
/*
--- 238,244 ----
** (ado, 5/24/93)
*/
pt = _conv((t->tm_wday == 0) ? 7 : t->tm_wday,
! "%d", gsizep, pt);
continue;
case 'V':
/*
***************
*** 260,266 ****
** 1 falls on a Thursday, are December 29-31
** of the PREVIOUS year part of week 1???
** (ado 5/24/93)
! /*
** You are understood not to expect this.
*/
{
--- 261,267 ----
** 1 falls on a Thursday, are December 29-31
** of the PREVIOUS year part of week 1???
** (ado 5/24/93)
! **
** You are understood not to expect this.
*/
{
***************
*** 269,275 ****
i = (t->tm_yday + 10 - (t->tm_wday ?
(t->tm_wday - 1) : 6)) / 7;
pt = _conv((i == 0) ? 53 : i,
! 2, '0', gsizep, pt);
}
continue;
case 'v':
--- 270,276 ----
i = (t->tm_yday + 10 - (t->tm_wday ?
(t->tm_wday - 1) : 6)) / 7;
pt = _conv((i == 0) ? 53 : i,
! "%02d", gsizep, pt);
}
continue;
case 'v':
***************
*** 284,300 ****
pt = _conv((t->tm_yday + 7 -
(t->tm_wday ?
(t->tm_wday - 1) : 6)) / 7,
! 2, '0', gsizep, pt);
continue;
case 'w':
! pt = _conv(t->tm_wday, 1, '0', gsizep, pt);
continue;
case 'y':
pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
! 2, '0', gsizep, pt);
continue;
case 'Y':
! pt = _conv(t->tm_year + TM_YEAR_BASE, 4, '0',
gsizep, pt);
continue;
case 'Z':
--- 285,301 ----
pt = _conv((t->tm_yday + 7 -
(t->tm_wday ?
(t->tm_wday - 1) : 6)) / 7,
! "%02d", gsizep, pt);
continue;
case 'w':
! pt = _conv(t->tm_wday, "%d", gsizep, pt);
continue;
case 'y':
pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
! "%02d", gsizep, pt);
continue;
case 'Y':
! pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d",
gsizep, pt);
continue;
case 'Z':
***************
*** 329,356 ****
}
static char *
! _conv(n, width, fill, gsizep, pt)
! int n, width, fill;
size_t *gsizep;
char *pt;
{
! char *p, *q, buf[12];
! static char digits[] = "0123456789";
! p = buf + sizeof buf;
! q = (width >= sizeof buf) ? buf : (p - width - 1);
! *--p = '\0';
! *--p = digits[n % 10];
! while (p > buf && (n /= 10) != 0)
! *--p = digits[n % 10];
! while (p > q)
! *--p = fill;
! return _add(p, gsizep, pt);
}
static char *
_add(str, gsizep, pt)
! char *str;
size_t *gsizep;
char *pt;
{
--- 330,350 ----
}
static char *
! _conv(n, format, gsizep, pt)
! int n;
! const char *format;
size_t *gsizep;
char *pt;
{
! char buf[21]; /* Room for - 2**63 ("-9223372036854775808") + null. */
! (void) sprintf(buf, format, n);
! return _add(buf, gsizep, pt);
}
static char *
_add(str, gsizep, pt)
! const char *str;
size_t *gsizep;
char *pt;
{
More information about the tz
mailing list