diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index 6829d4d..e85c29c 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -215,20 +215,20 @@ static const uint8_t jump_table[] =
     /* '4' */  8, /* '5' */  8, /* '6' */  8, /* '7' */  8,
     /* '8' */  8, /* '9' */  8,            0,            0,
 	       0,            0,            0,            0,
-	       0, /* 'A' */ 26,            0, /* 'C' */ 25,
-	       0, /* 'E' */ 19, /* F */   19, /* 'G' */ 19,
-	       0, /* 'I' */ 29,            0,            0,
+	       0, /* 'A' */ 27,            0, /* 'C' */ 26,
+	       0, /* 'E' */ 20, /* F */   20, /* 'G' */ 20,
+	       0, /* 'I' */ 30,            0,            0,
     /* 'L' */ 12,            0,            0,            0,
-	       0,            0,            0, /* 'S' */ 21,
+	       0,            0, /* 'R' */ 19, /* 'S' */ 22,
 	       0,            0,            0,            0,
     /* 'X' */ 18,            0, /* 'Z' */ 13,            0,
 	       0,            0,            0,            0,
-	       0, /* 'a' */ 26,            0, /* 'c' */ 20,
-    /* 'd' */ 15, /* 'e' */ 19, /* 'f' */ 19, /* 'g' */ 19,
-    /* 'h' */ 10, /* 'i' */ 15, /* 'j' */ 28,            0,
-    /* 'l' */ 11, /* 'm' */ 24, /* 'n' */ 23, /* 'o' */ 17,
-    /* 'p' */ 22, /* 'q' */ 12,            0, /* 's' */ 21,
-    /* 't' */ 27, /* 'u' */ 16,            0,            0,
+	       0, /* 'a' */ 27,            0, /* 'c' */ 21,
+    /* 'd' */ 15, /* 'e' */ 20, /* 'f' */ 20, /* 'g' */ 20,
+    /* 'h' */ 10, /* 'i' */ 15, /* 'j' */ 29,            0,
+    /* 'l' */ 11, /* 'm' */ 25, /* 'n' */ 24, /* 'o' */ 17,
+    /* 'p' */ 23, /* 'q' */ 12, /* 'r' */ 19, /* 's' */ 22,
+    /* 't' */ 28, /* 'u' */ 16,            0,            0,
     /* 'x' */ 18,            0, /* 'z' */ 13
   };
 
@@ -269,7 +269,7 @@ static const uint8_t jump_table[] =
 
 #define STEP0_3_TABLE							      \
     /* Step 0: at the beginning.  */					      \
-    static JUMP_TABLE_TYPE step0_jumps[30] =				      \
+    static JUMP_TABLE_TYPE step0_jumps[31] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (flag_space),		/* for ' ' */				      \
@@ -290,6 +290,7 @@ static const uint8_t jump_table[] =
       REF (form_unsigned),	/* for 'u' */				      \
       REF (form_octal),		/* for 'o' */				      \
       REF (form_hexa),		/* for 'X', 'x' */			      \
+      REF (form_roman),		/* for 'R', 'r' */			      \
       REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
       REF (form_character),	/* for 'c' */				      \
       REF (form_string),	/* for 's', 'S' */			      \
@@ -303,7 +304,7 @@ static const uint8_t jump_table[] =
       REF (flag_i18n),		/* for 'I' */				      \
     };									      \
     /* Step 1: after processing width.  */				      \
-    static JUMP_TABLE_TYPE step1_jumps[30] =				      \
+    static JUMP_TABLE_TYPE step1_jumps[31] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (form_unknown),	/* for ' ' */				      \
@@ -324,6 +325,7 @@ static const uint8_t jump_table[] =
       REF (form_unsigned),	/* for 'u' */				      \
       REF (form_octal),		/* for 'o' */				      \
       REF (form_hexa),		/* for 'X', 'x' */			      \
+      REF (form_roman),		/* for 'R', 'r' */			      \
       REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
       REF (form_character),	/* for 'c' */				      \
       REF (form_string),	/* for 's', 'S' */			      \
@@ -337,7 +339,7 @@ static const uint8_t jump_table[] =
       REF (form_unknown)        /* for 'I' */				      \
     };									      \
     /* Step 2: after processing precision.  */				      \
-    static JUMP_TABLE_TYPE step2_jumps[30] =				      \
+    static JUMP_TABLE_TYPE step2_jumps[31] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (form_unknown),	/* for ' ' */				      \
@@ -358,6 +360,7 @@ static const uint8_t jump_table[] =
       REF (form_unsigned),	/* for 'u' */				      \
       REF (form_octal),		/* for 'o' */				      \
       REF (form_hexa),		/* for 'X', 'x' */			      \
+      REF (form_roman),		/* for 'R', 'r' */			      \
       REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
       REF (form_character),	/* for 'c' */				      \
       REF (form_string),	/* for 's', 'S' */			      \
@@ -371,7 +374,7 @@ static const uint8_t jump_table[] =
       REF (form_unknown)        /* for 'I' */				      \
     };									      \
     /* Step 3a: after processing first 'h' modifier.  */		      \
-    static JUMP_TABLE_TYPE step3a_jumps[30] =				      \
+    static JUMP_TABLE_TYPE step3a_jumps[31] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (form_unknown),	/* for ' ' */				      \
@@ -392,6 +395,7 @@ static const uint8_t jump_table[] =
       REF (form_unsigned),	/* for 'u' */				      \
       REF (form_octal),		/* for 'o' */				      \
       REF (form_hexa),		/* for 'X', 'x' */			      \
+      REF (form_roman),		/* for 'R', 'r' */			      \
       REF (form_unknown),	/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
       REF (form_unknown),	/* for 'c' */				      \
       REF (form_unknown),	/* for 's', 'S' */			      \
@@ -405,7 +409,7 @@ static const uint8_t jump_table[] =
       REF (form_unknown)        /* for 'I' */				      \
     };									      \
     /* Step 3b: after processing first 'l' modifier.  */		      \
-    static JUMP_TABLE_TYPE step3b_jumps[30] =				      \
+    static JUMP_TABLE_TYPE step3b_jumps[31] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (form_unknown),	/* for ' ' */				      \
@@ -426,6 +430,7 @@ static const uint8_t jump_table[] =
       REF (form_unsigned),	/* for 'u' */				      \
       REF (form_octal),		/* for 'o' */				      \
       REF (form_hexa),		/* for 'X', 'x' */			      \
+      REF (form_roman),		/* for 'R', 'r' */			      \
       REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
       REF (form_character),	/* for 'c' */				      \
       REF (form_string),	/* for 's', 'S' */			      \
@@ -441,7 +446,7 @@ static const uint8_t jump_table[] =
 
 #define STEP4_TABLE							      \
     /* Step 4: processing format specifier.  */				      \
-    static JUMP_TABLE_TYPE step4_jumps[30] =				      \
+    static JUMP_TABLE_TYPE step4_jumps[31] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (form_unknown),	/* for ' ' */				      \
@@ -462,6 +467,7 @@ static const uint8_t jump_table[] =
       REF (form_unsigned),	/* for 'u' */				      \
       REF (form_octal),		/* for 'o' */				      \
       REF (form_hexa),		/* for 'X', 'x' */			      \
+      REF (form_roman),		/* for 'R', 'r' */			      \
       REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
       REF (form_character),	/* for 'c' */				      \
       REF (form_string),	/* for 's', 'S' */			      \
@@ -741,6 +747,11 @@ static const uint8_t jump_table[] =
 	  break;							      \
 	}								      \
 									      \
+    LABEL (form_roman):							      \
+      /* Ancient Roman / Latin number. */				      \
+      roman(s, va_arg (ap, int), spec == L_('R'));			      \
+      break;							              \
+									      \
     LABEL (form_float):							      \
       {									      \
 	/* Floating-point number.  This is handled by printf_fp.c.  */	      \
@@ -1210,6 +1221,72 @@ static const uint8_t jump_table[] =
       break;
 #endif
 
+static const int numbers[] = { 1000, 900, 500, 400, 100, 90,
+			       50, 40, 10, 9, 5, 4, 1 };
+static const CHAR_T *_rul[] = { L_("M"), L_("CM"), L_("D"), L_("CD"), L_("C"),
+			      L_("XC"), L_("L"), L_("XL"), L_("X"),
+			      L_("IX"), L_("V"), L_("IV"), L_("I") };
+static const CHAR_T *_rll[] = { L_("m"), L_("cm"), L_("d"), L_("cd"), L_("c"),
+			      L_("xc"), L_("l"), L_("xl"), L_("x"),
+			      L_("ix"), L_("v"), L_("iv"), L_("i") };
+
+static void roman(FILE *s, long int num, int upper_case)
+{
+  /* used by outchar */
+  int done = 0;
+
+  const CHAR_T **letters = upper_case ? _rul : _rll;
+
+  if(!num)
+    {
+      outstring(L_("(nihil)"), 7);
+      return;
+    }
+
+  if(num < 0)
+    {
+      outchar(L_('-'));
+      num = -num;
+    }
+
+  if(num > 499999999)
+    {
+      outstring(L_("(infinitum)"), 11);
+      return;
+    }
+
+  if(num > 99999)
+    {
+      outchar(L_('|'));
+      roman(s, num / 100000, upper_case);
+      outchar(L_('|'));
+      num %= 100000;
+    }
+
+  if(num > 4999)
+    {
+      outchar(L_('_'));
+      roman(s, num / 1000, upper_case);
+      outchar(L_('_'));
+      num %= 1000;
+    }
+
+  for (int i = 0; i < sizeof(numbers) / sizeof(*numbers); i++)
+    {
+      while (num >= numbers[i])
+	{
+	  outchar(letters[i][0]);
+	  if(letters[i][1])
+	  outchar(letters[i][1]);
+	  num -= numbers[i];
+	}
+    }
+
+  /* suppress warnings */
+  all_done:
+  return;
+}
+
 /* Helper function to provide temporary buffering for unbuffered streams.  */
 static int buffered_vfprintf (FILE *stream, const CHAR_T *fmt, va_list)
      __THROW __attribute__ ((noinline)) internal_function;
