Index: strftime.3
===================================================================
RCS file: /cvs/src/lib/libc/stdtime/strftime.3,v
retrieving revision 1.4
diff -u -r1.4 strftime.3
--- strftime.3	19 Oct 2008 20:15:58 -0000	1.4
+++ strftime.3	30 Oct 2008 22:27:41 -0000
@@ -220,6 +220,15 @@
 is replaced by national representation of the date and time
 (the format is similar to that produced by
 .Xr date 1 ) .
+.It Cm \&%-*
+GNU libc extension.
+Do not do any padding when performing numerical outputs.
+.It Cm \&%_*
+GNU libc extension.
+Explicitly specify space for padding.
+.It Cm \&%0*
+GNU libc extension.
+Explicitly specify zero for padding.
 .It Cm %%
 is replaced by
 .Ql % .
Index: strftime.c
===================================================================
RCS file: /cvs/src/lib/libc/stdtime/strftime.c,v
retrieving revision 1.7
diff -u -r1.7 strftime.c
--- strftime.c	19 Oct 2008 20:15:58 -0000	1.7
+++ strftime.c	30 Oct 2008 22:39:36 -0000
@@ -67,7 +67,7 @@
 static char *	_conv(int, const char *, char *, const char *);
 static char *	_fmt(const char *, const struct tm *, char *,
 		     const char *, int *);
-static char *	_yconv(int, int, int, int, char *, const char *);
+static char *	_yconv(int, int, int, int, int, char *, const char *);
 
 #define NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
 
@@ -80,6 +80,30 @@
 #define IN_THIS	2
 #define IN_ALL	3
 
+#define PAD_DEFAULT 0
+#define PAD_LESS	1
+#define PAD_SPACE	2
+#define PAD_ZERO	3
+
+static const char* fmt_padding[][4] = {
+	/* DEFAULT,	LESS,	SPACE,	ZERO */
+#define PAD_FMT_MONTHDAY	0
+#define PAD_FMT_HMS		0
+#define PAD_FMT_CENTURY		0
+#define PAD_FMT_SHORTYEAR	0
+#define PAD_FMT_MONTH		0
+#define PAD_FMT_WEEKOFYEAR	0
+#define PAD_FMT_DAYOFMONTH	0
+	{ "%02d",	"%d",	"%2d",	"%02d" },
+#define PAD_FMT_SDAYOFMONTH	1
+#define PAD_FMT_SHMS		1
+	{ "%2d",	"%d",	"%2d",	"%02d" },
+#define	PAD_FMT_DAYOFYEAR	2
+	{ "%03d",	"%d",	"%3d",	"%03d" },
+#define PAD_FMT_YEAR		3
+	{ "%04d",	"%d",	"%4d",	"%04d" }
+};
+
 size_t
 strftime(char * const s, const size_t maxsize, const char * const format,
 	 const struct tm * const t)
@@ -116,8 +140,11 @@
 _fmt(const char *format, const struct tm * const t, char *pt,
      const char * const ptlim, int * warnp)
 {
+	int	padopt;
+
 	for ( ; *format; ++format) {
 		if (*format == '%') {
+			padopt	 = PAD_DEFAULT;
 label:
 			switch (*++format) {
 			case '\0':
@@ -156,7 +183,7 @@
 				** something completely different.
 				** (ado, 1993-05-24)
 				*/
-				pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
+				pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0, padopt,
 					pt, ptlim);
 				continue;
 			case 'c':
@@ -174,7 +201,8 @@
 				pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
 				continue;
 			case 'd':
-				pt = _conv(t->tm_mday, "%02d", pt, ptlim);
+				pt = _conv(t->tm_mday, fmt_padding[PAD_FMT_DAYOFMONTH][padopt],
+					pt, ptlim);
 				continue;
 			case 'E':
 			case 'O':
@@ -189,21 +217,24 @@
 				*/
 				goto label;
 			case 'e':
-				pt = _conv(t->tm_mday, "%2d", pt, ptlim);
+				pt = _conv(t->tm_mday,
+					fmt_padding[PAD_FMT_SDAYOFMONTH][padopt], pt, ptlim);
 				continue;
 			case 'F':
 				pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
 				continue;
 			case 'H':
-				pt = _conv(t->tm_hour, "%02d", pt, ptlim);
+				pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_HMS][padopt],
+					pt, ptlim);
 				continue;
 			case 'I':
 				pt = _conv((t->tm_hour % 12) ?
 					(t->tm_hour % 12) : 12,
-					"%02d", pt, ptlim);
+					fmt_padding[PAD_FMT_HMS][padopt], pt, ptlim);
 				continue;
 			case 'j':
-				pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
+				pt = _conv(t->tm_yday + 1,
+					fmt_padding[PAD_FMT_DAYOFYEAR][padopt], pt, ptlim);
 				continue;
 			case 'k':
 				/*
@@ -216,7 +247,8 @@
 				** "%l" have been swapped.
 				** (ado, 1993-05-24)
 				*/
-				pt = _conv(t->tm_hour, "%2d", pt, ptlim);
+				pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_SHMS][padopt],
+					pt, ptlim);
 				continue;
 #ifdef KITCHEN_SINK
 			case 'K':
@@ -238,13 +270,15 @@
 				*/
 				pt = _conv((t->tm_hour % 12) ?
 					(t->tm_hour % 12) : 12,
-					"%2d", pt, ptlim);
+					fmt_padding[PAD_FMT_SHMS][padopt], pt, ptlim);
 				continue;
 			case 'M':
-				pt = _conv(t->tm_min, "%02d", pt, ptlim);
+				pt = _conv(t->tm_min, fmt_padding[PAD_FMT_HMS][padopt],
+					pt, ptlim);
 				continue;
 			case 'm':
-				pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
+				pt = _conv(t->tm_mon + 1,
+					fmt_padding[PAD_FMT_MONTH][padopt], pt, ptlim);
 				continue;
 			case 'n':
 				pt = _add("\n", pt, ptlim);
@@ -262,7 +296,8 @@
 				pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
 				continue;
 			case 'S':
-				pt = _conv(t->tm_sec, "%02d", pt, ptlim);
+				pt = _conv(t->tm_sec, fmt_padding[PAD_FMT_HMS][padopt],
+					pt, ptlim);
 				continue;
 			case 's':
 				{
@@ -291,7 +326,7 @@
 			case 'U':
 				pt = _conv((t->tm_yday + DAYSPERWEEK -
 					t->tm_wday) / DAYSPERWEEK,
-					"%02d", pt, ptlim);
+					fmt_padding[PAD_FMT_WEEKOFYEAR][padopt], pt, ptlim);
 				continue;
 			case 'u':
 				/*
@@ -382,13 +417,13 @@
 							w = 53;
 #endif /* defined XPG4_1994_04_09 */
 					if (*format == 'V')
-						pt = _conv(w, "%02d",
+						pt = _conv(w, fmt_padding[PAD_FMT_SHORTYEAR][padopt],
 							pt, ptlim);
 					else if (*format == 'g') {
 						*warnp = IN_ALL;
-						pt = _yconv(year, base, 0, 1,
+						pt = _yconv(year, base, 0, 1, padopt,
 							pt, ptlim);
-					} else	pt = _yconv(year, base, 1, 1,
+					} else	pt = _yconv(year, base, 1, 1, padopt,
 							pt, ptlim);
 				}
 				continue;
@@ -405,7 +440,7 @@
 					(t->tm_wday ?
 					(t->tm_wday - 1) :
 					(DAYSPERWEEK - 1))) / DAYSPERWEEK,
-					"%02d", pt, ptlim);
+					fmt_padding[PAD_FMT_WEEKOFYEAR][padopt], pt, ptlim);
 				continue;
 			case 'w':
 				pt = _conv(t->tm_wday, "%d", pt, ptlim);
@@ -426,11 +461,11 @@
 				continue;
 			case 'y':
 				*warnp = IN_ALL;
-				pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
+				pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1, padopt,
 					pt, ptlim);
 				continue;
 			case 'Y':
-				pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
+				pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1, padopt,
 					pt, ptlim);
 				continue;
 			case 'Z':
@@ -528,13 +563,29 @@
 				diff /= SECSPERMIN;
 				diff = (diff / MINSPERHOUR) * 100 +
 					(diff % MINSPERHOUR);
-				pt = _conv(diff, "%04d", pt, ptlim);
+				pt = _conv(diff, fmt_padding[PAD_FMT_YEAR][padopt],
+					pt, ptlim);
 				}
 				continue;
 			case '+':
 				pt = _fmt(Locale->d_t_fmt, t, pt, ptlim,
 					warnp);
 				continue;
+			case '-':
+				if (padopt != PAD_DEFAULT)
+					break;
+				padopt = PAD_LESS;
+				goto label;
+			case '_':
+				if (padopt != PAD_DEFAULT)
+					break;
+				padopt = PAD_SPACE;
+				goto label;
+			case '0':
+				if (padopt != PAD_DEFAULT)
+					break;
+				padopt = PAD_ZERO;
+				goto label;
 			case '%':
 			/*
 			** X311J/88-090 (4.12.3.5): if conversion char is
@@ -580,7 +631,7 @@
 
 static char *
 _yconv(const int a, const int b, const int convert_top, const int convert_yy,
-       char *pt, const char * const ptlim)
+       const int padopt, char *pt, const char * const ptlim)
 {
 	int	lead;
 	int	trail;
@@ -599,9 +650,9 @@
 	if (convert_top) {
 		if (lead == 0 && trail < 0)
 			pt = _add("-0", pt, ptlim);
-		else	pt = _conv(lead, "%02d", pt, ptlim);
+		else	pt = _conv(lead, fmt_padding[PAD_FMT_SHORTYEAR][padopt], pt, ptlim);
 	}
 	if (convert_yy)
-		pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
+		pt = _conv(((trail < 0) ? -trail : trail), fmt_padding[PAD_FMT_SHORTYEAR][padopt], pt, ptlim);
 	return pt;
 }
