summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--stream.c22
2 files changed, 17 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 3281ad6a..9fee44f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2012-09-16 Kaz Kylheku <kaz@kylheku.com>
+ * 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.
+
+2012-09-16 Kaz Kylheku <kaz@kylheku.com>
+
* parser.l: Implemented hexadecimal integer constants.
These will be very useful since bit operations are about
to be implemented.
diff --git a/stream.c b/stream.c
index e3d8d962..c430f2ee 100644
--- a/stream.c
+++ b/stream.c
@@ -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':