Skip to content

Commit

Permalink
Merge pull request #169 from DrXiao/fix-libc
Browse files Browse the repository at this point in the history
Ensure correctness of formatted output conversion
  • Loading branch information
jserv authored Dec 2, 2024
2 parents 861d7d2 + b310322 commit 18e005d
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 76 deletions.
135 changes: 61 additions & 74 deletions lib/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,19 +166,31 @@ void __str_base10(char *pb, int val)

void __str_base8(char *pb, int val)
{
int c = INT_BUF_LEN - 1;
while (c > 0) {
int v = val & 0x7;
int c = INT_BUF_LEN - 1, v;
/*
* Because every 3 binary digits can be converted
* to 1 octal digit, here performs the conversion
* 10 times, derived from 32 divided by 3.
*
* Finally, the remaining 2 bits are processed after
* the loop.
* */
int times = (sizeof(int) << 3) / 3;
for (int i = 0; i < times; i++) {
v = val & 0x7;
pb[c] = '0' + v;
val = val >> 3;
c--;
}
v = val & 0x3;
pb[c] = '0' + v;
}

void __str_base16(char *pb, int val)
{
int c = INT_BUF_LEN - 1;
while (c > 0) {
int times = sizeof(int) << 1;
for (int i = 0; i < times; i++) {
int v = val & 0xf;
if (v < 10)
pb[c] = '0' + v;
Expand All @@ -202,37 +214,13 @@ int __format(char *buffer,
{
int bi = 0;
char pb[INT_BUF_LEN];
int pbi = 0;

if (alternate_form == 1) {
switch (base) {
case 8:
/* octal */
buffer[0] = '0';
bi = 1;
width -= 1;
break;
case 16:
/* hex */
buffer[0] = '0';
buffer[1] = 'x';
bi = 2;
width -= 2;
break;
default:
/* decimal */
/* do nothing */
break;
}
if (width < 0)
width = 0;
}
int pbi;

/* set to zeroes */
while (pbi < INT_BUF_LEN) {
for (pbi = 0; pbi < INT_BUF_LEN; pbi++)
pb[pbi] = '0';
pbi++;
}

pbi = 0;

switch (base) {
case 8:
Expand All @@ -249,53 +237,52 @@ int __format(char *buffer,
break;
}

while (width > INT_BUF_LEN) {
/* need to add extra padding */
if (zeropad == 1)
buffer[bi] = '0';
else
buffer[bi] = ' ';
bi++;
width--;
}
while (pb[pbi] == '0' && pbi < INT_BUF_LEN - 1)
pbi++;

/* no padding */
if (width == 0) {
int c = 0;
int started = 0;

/* output from first digit */
while (c < INT_BUF_LEN) {
if (pb[c] != '0')
started = 1;
if (started) {
buffer[bi] = pb[c];
bi++;
}
c++;
switch (base) {
case 8:
if (alternate_form) {
if (width && zeropad && pb[pbi] != '0') {
buffer[bi++] = '0';
width -= 1;
} else if (pb[pbi] != '0')
pb[--pbi] = '0';
}
/* special case - zero */
if (started == 0) {
buffer[bi] = '0';
bi++;
break;
case 10:
if (width && zeropad && pb[pbi] == '-') {
buffer[bi++] = '-';
pbi++;
width--;
}
} else {
/* padding */
int c = INT_BUF_LEN - width;
int started = 0;
while (c < INT_BUF_LEN) {
if (pb[c] != '0')
started = 1;
if (started)
buffer[bi] = pb[c];
else if (zeropad == 1)
buffer[bi] = '0';
else
buffer[bi] = ' ';
bi++;
c++;
break;
case 16:
if (alternate_form) {
if (width && zeropad && pb[pbi] != '0') {
buffer[bi++] = '0';
buffer[bi++] = 'x';
width -= 2;
} else if (pb[pbi] != '0') {
pb[--pbi] = 'x';
pb[--pbi] = '0';
}
}
break;
}

width -= (INT_BUF_LEN - pbi);
if (width < 0)
width = 0;

while (width) {
buffer[bi++] = zeropad ? '0' : ' ';
width--;
}

for (; pbi < INT_BUF_LEN; pbi++)
buffer[bi++] = pb[pbi];

return bi;
}

Expand Down
121 changes: 121 additions & 0 deletions tests/driver.sh
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,127 @@ int main() {
}
EOF

fmt_ans="0x0000000000000000000000ff00cde1
0xff00cde1
000000000000000000000000ff00cde1
ff00cde1
0xff00cde1
ff00cde1
0x00ff00cde1
0xff00cde1
0000ff00cde1
ff00cde1
00000000000000000000037700146741
037700146741
00000000000000000000037700146741
37700146741
037700146741
37700146741
037700146741
037700146741
037700146741
37700146741
-0000000000000000000000016724511
-16724511
-16724511
-00016724511
-16724511
0x0000000000000000000000fffff204
0xfffff204
000000000000000000000000fffff204
fffff204
0xfffff204
fffff204
0x00fffff204
0xfffff204
0000fffff204
fffff204
00000000000000000000037777771004
037777771004
00000000000000000000037777771004
37777771004
037777771004
37777771004
037777771004
037777771004
037777771004
37777771004
-0000000000000000000000000003580
-3580
-3580
-00000003580
-3580
0x00000000000000000000000001000c
0x1000c
0000000000000000000000000001000c
1000c
0x1000c
1000c
0x000001000c
0x1000c
00000001000c
1000c
00000000000000000000000000200014
0200014
00000000000000000000000000200014
200014
0200014
200014
000000200014
0200014
000000200014
200014
00000000000000000000000000065548
65548
65548
000000065548
65548
00000000000000000000000000000000
0
00000000000000000000000000000000
0
0
0
000000000000
0
000000000000
0
00000000000000000000000000000000
0
00000000000000000000000000000000
0
0
0
000000000000
0
000000000000
0
00000000000000000000000000000000
0
0
000000000000
0"

try_output 0 "$fmt_ans" << EOF
void printf_conversion(int num) {
printf("%#032x\n%#32x\n%032x\n%32x\n%#x\n%x\n", num, num, num, num, num, num);
printf("%#012x\n%#12x\n%012x\n%12x\n", num, num, num, num);
printf("%#032o\n%#32o\n%032o\n%32o\n%#o\n%o\n", num, num, num, num, num, num);
printf("%#012o\n%#12o\n%012o\n%12o\n", num, num, num, num);
printf("%032d\n%32d\n%d\n", num, num, num);
printf("%012d\n%12d\n", num, num);
}
int main() {
int a = 0xFF00CDE1, b = 0xFFFFF204, c = 65548, d = 0;
printf_conversion(a);
printf_conversion(b);
printf_conversion(c);
printf_conversion(d);
return 0;
}
EOF

try_ 0 << EOF
int main() {
return '\0';
Expand Down
2 changes: 1 addition & 1 deletion tests/snapshots/fib.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/snapshots/hello.json

Large diffs are not rendered by default.

0 comments on commit 18e005d

Please sign in to comment.