diff --git a/winsup/cygwin/smallprint.cc b/winsup/cygwin/smallprint.cc index 8553f7002..9a4a1c897 100644 --- a/winsup/cygwin/smallprint.cc +++ b/winsup/cygwin/smallprint.cc @@ -13,13 +13,46 @@ details. */ #include #include +/* + 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':