https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=488221cf5c5263ba1a82391c80c00b8157e362cc

commit 488221cf5c5263ba1a82391c80c00b8157e362cc
Author: Corinna Vinschen <cori...@vinschen.de>
Date:   Fri Mar 2 18:09:35 2018 +0100

    Cygwin: small_s[w]printf: add '_' modifier to print lower case hex digits
    
    Signed-off-by: Corinna Vinschen <cori...@vinschen.de>

Diff:
---
 winsup/cygwin/smallprint.cc | 120 +++++++++++++++++++++++++++-----------------
 1 file changed, 74 insertions(+), 46 deletions(-)

diff --git a/winsup/cygwin/smallprint.cc b/winsup/cygwin/smallprint.cc
index 8553f70..9a4a1c8 100644
--- a/winsup/cygwin/smallprint.cc
+++ b/winsup/cygwin/smallprint.cc
@@ -13,13 +13,46 @@ details. */
 #include <ctype.h>
 #include <wchar.h>
 
+/*
+  Meaning of format conversion specifiers.  If 'l' isn't explicitely mentioned,
+  it's ignored!
+
+   0       modifier: pad with zero instead of spaces
+   0-9     modifier: field length
+   +       modifier: always add sign
+   l       modifier to d, o, R, u, x, y: 4 byte on 32 bit, 8 byte on 64 bit
+   l       modifier to s, S, W: non-ASCII tweaking
+   _       modifier: print lower case hex chars a-f instead of A-F
+
+   c       char
+   C       WCHAR/wchar_t
+   d       signed int, 4 byte
+   D       signed long long, 8 byte
+   E       GetLastError
+   o       octal unsigned int, 4 byte
+   O       octal unsigned long long, 8 byte
+   p       address
+   P       process name
+   R       return value, 4 byte.
+   s       char *
+   S       PUNICODE_STRING
+   u       unsigned int, 4 byte
+   U       unsigned long long, 8 byte
+   W       PWCHAR/wchar_t *
+   x       hex unsigned int, 4 byte
+   X       hex unsigned long long, 8 byte
+   y       0x hex unsigned int, 4 byte
+   Y       0x hex unsigned long long, 8 byte
+*/
+
 #define LLMASK (0xffffffffffffffffULL)
 #define LMASK  (0xffffffff)
 
 #define rnarg(dst, base, dosign, len, pad) __rn ((dst), (base), (dosign), 
va_arg (ap, int32_t), len, pad, LMASK)
 #define rnargLL(dst, base, dosign, len, pad) __rn ((dst), (base), (dosign), 
va_arg (ap, uint64_t), len, pad, LLMASK)
 
-static const char hex_str[] = "0123456789ABCDEF";
+static const char hex_str_upper[] = "0123456789ABCDEF";
+static const char hex_str_lower[] = "0123456789abcdef";
 
 class tmpbuf
 {
@@ -56,6 +89,15 @@ __rn (char *dst, int base, int dosign, long long val, int 
len, int pad, unsigned
   unsigned long long uval = 0;
   char res[20];
   int l = 0;
+  const char *hex_str;
+
+  if (base < 0)
+    {
+      base = -base;
+      hex_str = hex_str_lower;
+    }
+  else
+    hex_str = hex_str_upper;
 
   if (dosign && val < 0)
     {
@@ -88,40 +130,6 @@ __rn (char *dst, int base, int dosign, long long val, int 
len, int pad, unsigned
   return dst;
 }
 
-/*
-  Meaning of format conversion specifiers.  If 'l' isn't explicitely mentioned,
-  it's ignored!
-
-   c       char
-   C       WCHAR/wchar_t
-   d       signed int, 4 byte
-  ld       signed long, 4 byte on 32 bit, 8 byte on 64 bit
-   D       signed long long, 8 byte
-   E       GetLastError
-   o       octal unsigned int, 4 byte
-  lo       octal unsigned long, 4 byte on 32 bit, 8 byte on 64 bit
-   O       octal unsigned long long, 8 byte
-   p       address
-   P       process name
-   R       return value, 4 byte.
-  lR       return value, 4 byte on 32 bit, 8 byte on 64 bit.
-   s       char *
-  ls       char * w/ non-ASCII tweaking
-   S       PUNICODE_STRING
-  lS       PUNICODE_STRING w/ non-ASCII tweaking
-   u       unsigned int, 4 byte
-  lu       unsigned long, 4 byte on 32 bit, 8 byte on 64 bit
-   U       unsigned long long, 8 byte
-   W       PWCHAR/wchar_t *
-  lW       PWCHAR/wchar_t * w/ non-ASCII tweaking
-   x       hex unsigned int, 4 byte
-  lx       hex unsigned long, 4 byte on 32 bit, 8 byte on 64 bit
-   X       hex unsigned long long, 8 byte
-   y       0x hex unsigned int, 4 byte
-  ly       0x hex unsigned long, 4 byte on 32 bit, 8 byte on 64 bit
-   Y       0x hex unsigned long long, 8 byte
-*/
-
 int
 __small_vsprintf (char *dst, const char *fmt, va_list ap)
 {
@@ -139,6 +147,9 @@ __small_vsprintf (char *dst, const char *fmt, va_list ap)
     {
       int i, n = 0x7fff;
       bool l_opt = false;
+      /* set to -1 on '_', indicates upper (1)/lower(-1) case */
+      int h_opt = 1;
+      const char *hex_str = hex_str_upper;
       if (*fmt != '%')
        *dst++ = *fmt++;
       else
@@ -170,13 +181,16 @@ __small_vsprintf (char *dst, const char *fmt, va_list ap)
                      continue;
                    }
                  /*FALLTHRU*/
-               case '1': case '2': case '3': case '4':
-               case '5': case '6': case '7': case '8': case '9':
+               case '1' ... '9':
                  len = len * 10 + (c - '0');
                  continue;
                case 'l':
                  l_opt = true;
                  continue;
+               case '_':
+                 h_opt = -1;
+                 hex_str = hex_str_lower;
+                 continue;
                case 'c':
                  {
                    unsigned char c = (va_arg (ap, int) & 0xff);
@@ -186,7 +200,7 @@ __small_vsprintf (char *dst, const char *fmt, va_list ap)
                      {
                        *dst++ = '0';
                        *dst++ = 'x';
-                       dst = __rn (dst, 16, 0, c, len, pad, LMASK);
+                       dst = __rn (dst, h_opt * 16, 0, c, len, pad, LMASK);
                      }
                  }
                  break;
@@ -249,7 +263,7 @@ __small_vsprintf (char *dst, const char *fmt, va_list ap)
                    goto gen_decimalLL;
 #endif
 gen_decimal:
-                 dst = rnarg (dst, base, addsign, len, pad);
+                 dst = rnarg (dst, h_opt * base, addsign, len, pad);
                  break;
                case 'D':
                  base = 10;
@@ -270,15 +284,15 @@ gen_decimal:
                  base = 16;
                  addsign = 0;
 gen_decimalLL:
-                 dst = rnargLL (dst, base, addsign, len, pad);
+                 dst = rnargLL (dst, h_opt * base, addsign, len, pad);
                  break;
                case 'p':
                  *dst++ = '0';
                  *dst++ = 'x';
 #ifdef __x86_64__
-                 dst = rnargLL (dst, 16, 0, len, pad);
+                 dst = rnargLL (dst, h_opt * 16, 0, len, pad);
 #else
-                 dst = rnarg (dst, 16, 0, len, pad);
+                 dst = rnarg (dst, h_opt * 16, 0, len, pad);
 #endif
                  break;
                case '.':
@@ -432,6 +446,15 @@ __wrn (PWCHAR dst, int base, int dosign, long long val, 
int len, int pad, unsign
   unsigned long long uval = 0;
   WCHAR res[20];
   int l = 0;
+  const char *hex_str;
+
+  if (base < 0)
+    {
+      base = -base;
+      hex_str = hex_str_lower;
+    }
+  else
+    hex_str = hex_str_upper;
 
   if (dosign && val < 0)
     {
@@ -483,6 +506,8 @@ __small_vswprintf (PWCHAR dst, const WCHAR *fmt, va_list ap)
 #ifdef __x86_64__
       bool l_opt = false;
 #endif
+      /* set to -1 on '_', indicates upper (1)/lower(-1) case */
+      int h_opt = 1;
       if (*fmt != L'%')
        *dst++ = *fmt++;
       else
@@ -522,6 +547,9 @@ __small_vswprintf (PWCHAR dst, const WCHAR *fmt, va_list ap)
                  l_opt = true;
 #endif
                  continue;
+               case '_':
+                 h_opt = -1;
+                 continue;
                case L'c':
                case L'C':
                  *dst++ = va_arg (ap, unsigned);
@@ -576,7 +604,7 @@ __small_vswprintf (PWCHAR dst, const WCHAR *fmt, va_list ap)
                    goto gen_decimalLL;
 #endif
 gen_decimal:
-                 dst = wrnarg (dst, base, addsign, len, pad);
+                 dst = wrnarg (dst, h_opt * base, addsign, len, pad);
                  break;
                case 'D':
                  base = 10;
@@ -597,15 +625,15 @@ gen_decimal:
                  base = 16;
                  addsign = 0;
 gen_decimalLL:
-                 dst = wrnargLL (dst, base, addsign, len, pad);
+                 dst = wrnargLL (dst, h_opt * base, addsign, len, pad);
                  break;
                case L'p':
                  *dst++ = L'0';
                  *dst++ = L'x';
 #ifdef __x86_64__
-                 dst = wrnargLL (dst, 16, 0, len, pad);
+                 dst = wrnargLL (dst, h_opt * 16, 0, len, pad);
 #else
-                 dst = wrnarg (dst, 16, 0, len, pad);
+                 dst = wrnarg (dst, h_opt * 16, 0, len, pad);
 #endif
                  break;
                case L'P':

Reply via email to