diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index 970e58f46..fb697e0e7 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,3 +1,11 @@
+2012-01-13  Yaakov Selkowitz  <yselkowitz@users.sourceforge.net>
+
+	* libc/stdio/sprintf.c: Document 'm' conversion specifier.
+	* libc/stdio/swprintf.c: Ditto.
+	* libc/stdio/vfprintf.c (_VFPRINTF_R) [_GLIBC_EXTENSION]: Handle 'm'
+	conversion specifier.
+	* libc/stdio/vfwprintf.c (_VFWPRINTF_R) [_GLIBC_EXTENSION]: Ditto.
+
 2012-01-12  Yaakov Selkowitz  <yselkowitz@users.sourceforge.net>
 
 	* libc/include/tgmath.h: New header.
diff --git a/newlib/libc/stdio/sprintf.c b/newlib/libc/stdio/sprintf.c
index 072622e75..0914b23b8 100644
--- a/newlib/libc/stdio/sprintf.c
+++ b/newlib/libc/stdio/sprintf.c
@@ -518,6 +518,10 @@ DESCRIPTION
 			implementation is similar to <<%#tx>>), except
 			that <<0x>> appears even for the NULL pointer.
 
+		o m
+			Prints the output of <<strerror(errno)>>; no
+			argument is required.  A GNU extension.
+
 		o-
 	O-
 
diff --git a/newlib/libc/stdio/swprintf.c b/newlib/libc/stdio/swprintf.c
index 63480176a..4e964bedd 100644
--- a/newlib/libc/stdio/swprintf.c
+++ b/newlib/libc/stdio/swprintf.c
@@ -498,6 +498,10 @@ DESCRIPTION
 			implementation is similar to <<%#tx>>), except
 			that <<0x>> appears even for the NULL pointer.
 
+		o m
+			Prints the output of <<strerror(errno)>>; no
+			argument is required.  A GNU extension.
+
 		o-
 	O-
 
diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c
index be35d248c..e3fc099d3 100644
--- a/newlib/libc/stdio/vfprintf.c
+++ b/newlib/libc/stdio/vfprintf.c
@@ -1225,6 +1225,15 @@ reswitch:	switch (ch) {
 				sign = '-';
 			break;
 #endif /* FLOATING_POINT */
+#ifdef _GLIBC_EXTENSION
+		case 'm':  /* extension */
+			{
+				int dummy;
+				cp = _strerror_r (data, data->_errno, 1, &dummy);
+			}
+			flags &= ~LONGINT;
+			goto string;
+#endif
 		case 'n':
 #ifndef _NO_LONGLONG
 			if (flags & QUADINT)
@@ -1272,8 +1281,11 @@ reswitch:	switch (ch) {
 #ifdef _WANT_IO_C99_FORMATS
 		case 'S':
 #endif
-			sign = '\0';
 			cp = GET_ARG (N, ap, char_ptr_t);
+#ifdef _GLIBC_EXTENSION
+string:
+#endif
+			sign = '\0';
 #ifndef __OPTIMIZE_SIZE__
 			/* Behavior is undefined if the user passed a
 			   NULL string when precision is not 0.
diff --git a/newlib/libc/stdio/vfwprintf.c b/newlib/libc/stdio/vfwprintf.c
index 79020f386..d76fff0d6 100644
--- a/newlib/libc/stdio/vfwprintf.c
+++ b/newlib/libc/stdio/vfwprintf.c
@@ -1074,6 +1074,15 @@ reswitch:	switch (ch) {
 				sign = L'-';
 			break;
 #endif /* FLOATING_POINT */
+#ifdef _GLIBC_EXTENSION
+		case L'm':  /* GNU extension */
+			{
+				int dummy;
+				cp = (wchar_t *) _strerror_r (data, data->_errno, 1, &dummy);
+			}
+			flags &= ~LONGINT;
+			goto string;
+#endif
 		case L'n':
 #ifndef _NO_LONGLONG
 			if (flags & QUADINT)
@@ -1118,8 +1127,11 @@ reswitch:	switch (ch) {
 #ifdef _WANT_IO_C99_FORMATS
 		case L'S':	/* POSIX extension */
 #endif
-			sign = '\0';
 			cp = GET_ARG (N, ap, wchar_ptr_t);
+#ifdef _GLIBC_EXTENSION
+string:
+#endif
+			sign = '\0';
 #ifndef __OPTIMIZE_SIZE__
 			/* Behavior is undefined if the user passed a
 			   NULL string when precision is not 0.
@@ -1132,7 +1144,7 @@ reswitch:	switch (ch) {
 			else
 #endif /* __OPTIMIZE_SIZE__ */
 #ifdef _MB_CAPABLE
-			if (ch == L's' && !(flags & LONGINT)) {
+			if (ch != L'S' && !(flags & LONGINT)) {
 				char *arg = (char *) cp;
 				size_t insize = 0, nchars = 0, nconv = 0;
 				mbstate_t ps;