summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2016-11-22 10:29:08 +0200
committerRich Felker <dalias@aerifal.cx>2017-12-11 15:51:30 -0500
commit8a6bd7307da3fc4d08dd6a9277b611ccb4971354 (patch)
tree1d89a0d7a3bf79166c9ccd714259c33ecf605989
parent2488d31f5a946e63e40058baf29fd2991343ea6f (diff)
downloadmusl-8a6bd7307da3fc4d08dd6a9277b611ccb4971354.tar.gz
implement strftime padding specifier extensions
notes added by maintainer: the '-' specifier allows default padding to be suppressed, and '_' allows padding with spaces instead of the default (zeros). these extensions seem to be included in several other implementations including FreeBSD and derivatives, and Solaris. while portable software should not depend on them, time format strings are often exposed to the user for configurable time display. reportedly some python programs also use and depend on them.
-rw-r--r--src/time/strftime.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/src/time/strftime.c b/src/time/strftime.c
index a3039204..d1ca7cae 100644
--- a/src/time/strftime.c
+++ b/src/time/strftime.c
@@ -48,12 +48,12 @@ static int week_num(const struct tm *tm)
const char *__tm_to_tzname(const struct tm *);
size_t __strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t);
-const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc)
+const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc, int pad)
{
nl_item item;
long long val;
const char *fmt = "-";
- int width = 2;
+ int width = 2, def_pad = '0';
switch (f) {
case 'a':
@@ -79,15 +79,14 @@ const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *
case 'C':
val = (1900LL+tm->tm_year) / 100;
goto number;
+ case 'e':
+ def_pad = '_';
case 'd':
val = tm->tm_mday;
goto number;
case 'D':
fmt = "%m/%d/%y";
goto recu_strftime;
- case 'e':
- *l = snprintf(*s, sizeof *s, "%2d", tm->tm_mday);
- return *s;
case 'F':
fmt = "%Y-%m-%d";
goto recu_strftime;
@@ -200,7 +199,12 @@ const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *
return 0;
}
number:
- *l = snprintf(*s, sizeof *s, "%0*lld", width, val);
+ switch (pad ? pad : def_pad) {
+ case '-': *l = snprintf(*s, sizeof *s, "%lld", val); break;
+ case '_': *l = snprintf(*s, sizeof *s, "%*lld", width, val); break;
+ case '0':
+ default: *l = snprintf(*s, sizeof *s, "%0*lld", width, val); break;
+ }
return *s;
nl_strcat:
fmt = __nl_langinfo_l(item, loc);
@@ -221,7 +225,7 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st
char buf[100];
char *p;
const char *t;
- int plus;
+ int pad, plus;
unsigned long width;
for (l=0; l<n; f++) {
if (!*f) {
@@ -233,6 +237,8 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st
continue;
}
f++;
+ pad = 0;
+ if (*f == '-' || *f == '_' || *f == '0') pad = *f++;
if ((plus = (*f == '+'))) f++;
width = strtoul(f, &p, 10);
if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') {
@@ -242,7 +248,7 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st
}
f = p;
if (*f == 'E' || *f == 'O') f++;
- t = __strftime_fmt_1(&buf, &k, *f, tm, loc);
+ t = __strftime_fmt_1(&buf, &k, *f, tm, loc, pad);
if (!t) break;
if (width) {
for (; *t=='+' || *t=='-' || (*t=='0'&&t[1]); t++, k--);