mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Fix the X conversion specifier's alternative form (#788)
The standard states that, when the # flag is used: > The result is converted to an "alternative form". [...] For x (or X) conversion, a nonzero result has 0x (or 0X) prefixed to it. - C standard, 7.23.6.1. The fprintf function cosmopolitan fails to use the correct alternative form (0X) when the X conversion specifier is used, instead using 0x, which is not capitalized. This patch fixes this, along with the several tests that test for the wrong behavior.
This commit is contained in:
parent
a412ca7a77
commit
0adefbf152
4 changed files with 31 additions and 10 deletions
|
@ -317,6 +317,7 @@ _Hide int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
goto FormatNumber;
|
||||
case 'b':
|
||||
log2base = 1;
|
||||
alphabet = "0123456789abcdefpb";
|
||||
goto FormatNumber;
|
||||
case 'o':
|
||||
log2base = 3;
|
||||
|
|
|
@ -31,7 +31,7 @@ uint128_t __udivmodti4(uint128_t, uint128_t, uint128_t *);
|
|||
static int __fmt_ntoa_format(int out(const char *, void *, size_t), void *arg,
|
||||
char *buf, unsigned len, bool negative,
|
||||
unsigned log2base, unsigned prec, unsigned width,
|
||||
unsigned char flags) {
|
||||
unsigned char flags, const char *alphabet) {
|
||||
unsigned i;
|
||||
/* pad leading zeros */
|
||||
if (width && (flags & FLAGS_ZEROPAD) &&
|
||||
|
@ -53,10 +53,9 @@ static int __fmt_ntoa_format(int out(const char *, void *, size_t), void *arg,
|
|||
len--;
|
||||
}
|
||||
}
|
||||
if (log2base == 4 && len < BUFFER_SIZE) {
|
||||
buf[len++] = 'x';
|
||||
} else if (log2base == 1 && len < BUFFER_SIZE) {
|
||||
buf[len++] = 'b';
|
||||
if ((log2base == 4 || log2base == 1) && len < BUFFER_SIZE) {
|
||||
buf[len++] = alphabet[17]; // x, X or b (for the corresponding conversion
|
||||
// specifiers)
|
||||
}
|
||||
if (len < BUFFER_SIZE) {
|
||||
buf[len++] = '0';
|
||||
|
@ -122,7 +121,7 @@ int __fmt_ntoa2(int out(const char *, void *, size_t), void *arg,
|
|||
_npassert(count <= BUFFER_SIZE);
|
||||
}
|
||||
return __fmt_ntoa_format(out, arg, buf, len, neg, log2base, prec, width,
|
||||
flags);
|
||||
flags, alphabet);
|
||||
}
|
||||
|
||||
int __fmt_ntoa(int out(const char *, void *, size_t), void *arg, va_list va,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
|
@ -77,6 +78,26 @@ TEST(fmt, u) {
|
|||
TEST(fmt, x) {
|
||||
EXPECT_STREQ("0x01 ", _gc(xasprintf("%#-07.2x", 1)));
|
||||
EXPECT_STREQ("0x00136d ", _gc(xasprintf("%#-010.6x", 4973)));
|
||||
EXPECT_STREQ("0X1", _gc(xasprintf("%#X", 1)));
|
||||
EXPECT_STREQ("0XA", _gc(xasprintf("%#X", 10)));
|
||||
EXPECT_STREQ("0XFFFF", _gc(xasprintf("%#X", 65535)));
|
||||
EXPECT_STREQ("0XABCDEF", _gc(xasprintf("%#X", 0xABCDEF)));
|
||||
EXPECT_STREQ("0X1", _gc(xasprintf("%#hX", (short)1)));
|
||||
EXPECT_STREQ("0XA", _gc(xasprintf("%#hX", (short)10)));
|
||||
EXPECT_STREQ("0XFFFF", _gc(xasprintf("%#hX", (short)65535)));
|
||||
EXPECT_STREQ("0XABCD", _gc(xasprintf("%#hX", (short)0xABCD)));
|
||||
EXPECT_STREQ(" 0X308C6705", _gc(xasprintf("%#20X", 814507781)));
|
||||
EXPECT_STREQ("0X0000000000308C6705", _gc(xasprintf("%#020X", 814507781)));
|
||||
EXPECT_STREQ(" 0X6705",
|
||||
_gc(xasprintf("%#20hX", (short)814507781)));
|
||||
EXPECT_STREQ("0X000000000000006705",
|
||||
_gc(xasprintf("%#020hX", (short)814507781)));
|
||||
EXPECT_STREQ(" 0XABCDEF", _gc(xasprintf("%#20X", 0xABCDEF)));
|
||||
EXPECT_STREQ("0X000000000000ABCDEF", _gc(xasprintf("%#020X", 0xABCDEF)));
|
||||
EXPECT_STREQ(" 0XCDEF",
|
||||
_gc(xasprintf("%#20hX", (short)0xABCDEF)));
|
||||
EXPECT_STREQ("0X00000000000000CDEF",
|
||||
_gc(xasprintf("%#020hX", (short)0xABCDEF)));
|
||||
}
|
||||
|
||||
TEST(fmt, b) {
|
||||
|
|
|
@ -310,8 +310,8 @@ TEST(sprintf, test_padding_pound_020) {
|
|||
EXPECT_STREQ("00000000037777777001", Format("%#020o", 4294966785U));
|
||||
EXPECT_STREQ("0x00000000001234abcd", Format("%#020x", 305441741));
|
||||
EXPECT_STREQ("0x0000000000edcb5433", Format("%#020x", 3989525555U));
|
||||
EXPECT_STREQ("0x00000000001234ABCD", Format("%#020X", 305441741));
|
||||
EXPECT_STREQ("0x0000000000EDCB5433", Format("%#020X", 3989525555U));
|
||||
EXPECT_STREQ("0X00000000001234ABCD", Format("%#020X", 305441741));
|
||||
EXPECT_STREQ("0X0000000000EDCB5433", Format("%#020X", 3989525555U));
|
||||
}
|
||||
|
||||
TEST(sprintf, test_padding_pound_20) {
|
||||
|
@ -325,8 +325,8 @@ TEST(sprintf, test_padding_pound_20) {
|
|||
EXPECT_STREQ(" 037777777001", Format("%#20o", 4294966785U));
|
||||
EXPECT_STREQ(" 0x1234abcd", Format("%#20x", 305441741));
|
||||
EXPECT_STREQ(" 0xedcb5433", Format("%#20x", 3989525555U));
|
||||
EXPECT_STREQ(" 0x1234ABCD", Format("%#20X", 305441741));
|
||||
EXPECT_STREQ(" 0xEDCB5433", Format("%#20X", 3989525555U));
|
||||
EXPECT_STREQ(" 0X1234ABCD", Format("%#20X", 305441741));
|
||||
EXPECT_STREQ(" 0XEDCB5433", Format("%#20X", 3989525555U));
|
||||
}
|
||||
|
||||
TEST(sprintf, test_padding_20_point_5) {
|
||||
|
|
Loading…
Add table
Reference in a new issue