diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2012-09-16 12:28:25 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2012-09-16 12:28:25 -0700 |
commit | 14e48e6f78988bc323908df944fe0a534a38629d (patch) | |
tree | 963ddca6bf0e1e1e76362d9aa6d29e704af32fc1 /stream.c | |
parent | 04a89cc3d83a71b5c9b5df7088d2408e8f7b8a40 (diff) | |
download | txr-14e48e6f78988bc323908df944fe0a534a38629d.tar.gz txr-14e48e6f78988bc323908df944fe0a534a38629d.tar.bz2 txr-14e48e6f78988bc323908df944fe0a534a38629d.zip |
* stream.c (vformat): Fix bug in ~x format directive for printing
integers in hex. When we use the printf's %x conversion specifiers for
fixnums, we get incorrect results when the values are negative, because
the argument is actually treated as an unsigned integer.
The end result is that (format t "~x" -1) produces FFFFFFFF
rather than -1. Also, merged together mindless code duplication.
Diffstat (limited to 'stream.c')
-rw-r--r-- | stream.c | 22 |
1 files changed, 8 insertions, 14 deletions
@@ -1126,7 +1126,7 @@ val vformat(val stream, val fmtstr, va_list vl) case vf_spec: state = vf_init; switch (ch) { - case 'x': + case 'x': case 'X': obj = va_arg(vl, val); if (bignump(obj)) { int nchars = mp_radix_size(mp(obj), 16); @@ -1134,20 +1134,14 @@ val vformat(val stream, val fmtstr, va_list vl) pnum = (char *) chk_malloc(nchars + 1); mp_toradix_case(mp(obj), (unsigned char *) pnum, 16, 1); } else { + const char *fmt = ch == 'x' ? num_fmt->hex : num_fmt->HEX; value = c_num(obj); - sprintf(num_buf, num_fmt->hex, value); - } - goto output_num; - case 'X': - obj = va_arg(vl, val); - if (bignump(obj)) { - int nchars = mp_radix_size(mp(obj), 16); - if (nchars >= (int) sizeof (num_buf)) - pnum = (char *) chk_malloc(nchars + 1); - mp_toradix_case(mp(obj), (unsigned char *) pnum, 16, 0); - } else { - value = c_num(obj); - sprintf(num_buf, num_fmt->HEX, value); + if (value < 0) { + num_buf[0] = '-'; + sprintf(num_buf + 1, fmt, -value); + } else { + sprintf(num_buf, fmt, value); + } } goto output_num; case 'o': |