mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-08 10:50:28 +00:00
Fix printf alternative form+precision+octal bugs
The C standard states that: > For o conversion, it increases the precision, if and only if > necessary, to force the first digit of the result to be a zero (if > the value and precision are both 0, a single 0 is printed). - The C standard, 7.23.6.1.6. The fprintf function When printing numbers in their alternative form, with a precision and with a conversion specifier of o (octal), Cosmopolitan currently fails to obey this in two ways: 1. When printing a value with a precision that results in 0-padding, cosmopolitan would still add an extra 0 even though this should be done "if and only if necessary" 2. When printing a value of 0 with a precision of 0, nothing is printed, even though the standard specifically states that a single 0 is printed in this case This patch fixes this.
This commit is contained in:
parent
e816e97762
commit
54ed6ad4ac
2 changed files with 12 additions and 3 deletions
|
@ -46,8 +46,8 @@ static int __fmt_ntoa_format(int out(const char *, void *, size_t), void *arg,
|
||||||
}
|
}
|
||||||
/* handle hash */
|
/* handle hash */
|
||||||
if (flags & FLAGS_HASH) {
|
if (flags & FLAGS_HASH) {
|
||||||
if (!(flags & FLAGS_PRECISION) && len &&
|
if ((!(flags & FLAGS_PRECISION) || log2base == 3) && len &&
|
||||||
((len == prec) || (len == width)) && buf[len - 1] == '0') {
|
((len >= prec) || (len >= width)) && buf[len - 1] == '0') {
|
||||||
len--;
|
len--;
|
||||||
if (len && (log2base == 4 || log2base == 1) && buf[len - 1] == '0') {
|
if (len && (log2base == 4 || log2base == 1) && buf[len - 1] == '0') {
|
||||||
len--;
|
len--;
|
||||||
|
@ -95,7 +95,9 @@ int __fmt_ntoa2(int out(const char *, void *, size_t), void *arg,
|
||||||
unsigned len, count, digit;
|
unsigned len, count, digit;
|
||||||
char buf[BUFFER_SIZE];
|
char buf[BUFFER_SIZE];
|
||||||
len = 0;
|
len = 0;
|
||||||
if (!value) flags &= ~FLAGS_HASH;
|
/* we check for log2base != 3 because otherwise we'll print nothing for a value of 0 with precision 0 when # mandates that one be printed */
|
||||||
|
if (!value && log2base != 3)
|
||||||
|
flags &= ~FLAGS_HASH;
|
||||||
if (value || !(flags & FLAGS_PRECISION)) {
|
if (value || !(flags & FLAGS_PRECISION)) {
|
||||||
count = 0;
|
count = 0;
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -80,6 +80,13 @@ TEST(fmt, x) {
|
||||||
EXPECT_STREQ("0x00136d ", _gc(xasprintf("%#-010.6x", 4973)));
|
EXPECT_STREQ("0x00136d ", _gc(xasprintf("%#-010.6x", 4973)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(fmt, o) {
|
||||||
|
EXPECT_STREQ("0000000000000037777777634", _gc(xasprintf("%#.25o", -100)));
|
||||||
|
EXPECT_STREQ("0001777777777777777777634", _gc(xasprintf("%#.25lo", -100L)));
|
||||||
|
EXPECT_STREQ("0001777777777777777777634", _gc(xasprintf("%#.25llo", -100LL)));
|
||||||
|
EXPECT_STREQ("0", _gc(xasprintf("%#.o", 0)));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(fmt, b) {
|
TEST(fmt, b) {
|
||||||
EXPECT_STREQ("000010100 ", _gc(xasprintf("%-14.9b", 20)));
|
EXPECT_STREQ("000010100 ", _gc(xasprintf("%-14.9b", 20)));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue