summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-12-22 17:08:32 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-12-22 17:08:32 -0800
commit428519803e55041438569a590f15aa581c4a4737 (patch)
treefd337f2776aab33ff5b063e725f2394f90e48d4b
parentf27ee7385eef9199687239541156d700e01fb033 (diff)
downloadtxr-428519803e55041438569a590f15aa581c4a4737.tar.gz
txr-428519803e55041438569a590f15aa581c4a4737.tar.bz2
txr-428519803e55041438569a590f15aa581c4a4737.zip
Bug #35026
* stream.c (format_num): New argument: sign character. Rewrote to handle precision, width, zero padding and leading sign similarly to printf. (vformat): New syntax accepted: a space or + before the width specifies that a positive sign is to be explicitly written as a space or + character. Pass one more argument to vormat_num calls. Bugfix: go back to vf_init state after processing ~~.
-rw-r--r--ChangeLog13
-rw-r--r--stream.c46
2 files changed, 45 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 13cbb125..f1c2484d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
2011-12-22 Kaz Kylheku <kaz@kylheku.com>
+ Bug #35026
+
+ * stream.c (format_num): New argument: sign character.
+ Rewrote to handle precision, width, zero padding and
+ leading sign similarly to printf.
+ (vformat): New syntax accepted: a space or + before
+ the width specifies that a positive sign is to be
+ explicitly written as a space or + character.
+ Pass one more argument to vormat_num calls.
+ Bugfix: go back to vf_init state after processing ~~.
+
+2011-12-22 Kaz Kylheku <kaz@kylheku.com>
+
Bug #35136 and cleanup.
* arith.c (plus, minus, mul, gt, ge, lt, le, exptmod, gcd): Remove
diff --git a/stream.c b/stream.c
index 9f0b282f..146dcb56 100644
--- a/stream.c
+++ b/stream.c
@@ -767,22 +767,37 @@ static void detect_format_string(void)
}
static val vformat_num(val stream, const char *str,
- int width, int left, int pad, int precision)
+ int width, int left, int zeropad,
+ int precision, int sign)
{
- int len = strlen(str);
- int truewidth = (width > precision) ? width : precision;
- int slack = (len < truewidth) ? truewidth - len : 0;
- int padlen = (len < precision) ? precision - len : 0;
+ int sign_char = (str[0] == '-' || str[0] == '+') ? str[0] : 0;
+ int digit_len = strlen(str) - (sign_char != 0);
+ int padlen = precision > digit_len ? precision - digit_len : 0;
+ int total_len = digit_len + padlen + (sign_char || sign);
+ int slack = (total_len < width) ? width - total_len : 0;
int i;
if (!left)
for (i = 0; i < slack; i++)
- if (!put_char(stream, pad ? chr('0') : chr(' ')))
+ if (!put_char(stream, chr(' ')))
return nil;
- for (i = 0; i < padlen; i++)
- if (!put_char(stream, pad ? chr('0') : chr(' ')))
- return nil;
+ if (!zeropad)
+ for (i = 0; i < padlen; i++)
+ if (!put_char(stream, chr(' ')))
+ return nil;
+
+ if (sign_char) {
+ put_char(stream, chr(sign_char));
+ str++;
+ } else if (sign) {
+ put_char(stream, chr(sign));
+ }
+
+ if (zeropad)
+ for (i = 0; i < padlen; i++)
+ if (!put_char(stream, chr('0')))
+ return nil;
while (*str)
if (!put_char(stream, chr(*str++)))
@@ -834,7 +849,7 @@ val vformat(val stream, val fmtstr, va_list vl)
vf_init, vf_width, vf_digits, vf_precision, vf_spec
} state = vf_init, saved_state = vf_init;
int width = 0, precision = 0, digits = 0;
- int left = 0, zeropad = 0;
+ int left = 0, sign = 0, zeropad = 0;
cnum value;
void *ptr;
@@ -865,10 +880,14 @@ val vformat(val stream, val fmtstr, va_list vl)
switch (ch) {
case '~':
put_char(stream, chr('~'));
+ state = vf_init;
continue;
case '-':
left = 1;
continue;
+ case '+': case ' ':
+ sign = ch;
+ continue;
case ',':
state = vf_precision;
continue;
@@ -1013,7 +1032,7 @@ val vformat(val stream, val fmtstr, va_list vl)
if (fixnump(obj)) {
value = c_num(obj);
sprintf(num_buf, num_fmt->dec, value);
- if (!vformat_num(stream, num_buf, 0, 0, 0, 0))
+ if (!vformat_num(stream, num_buf, 0, 0, 0, 0, 0))
return nil;
continue;
} else if (bignump(obj)) {
@@ -1022,7 +1041,7 @@ val vformat(val stream, val fmtstr, va_list vl)
if (nchars >= (int) sizeof (num_buf))
pnum = (char *) chk_malloc(nchars + 1);
mp_toradix(mp(obj), (unsigned char *) pnum, 10);
- res = vformat_num(stream, pnum, 0, 0, 0, 0);
+ res = vformat_num(stream, pnum, 0, 0, 0, 0, 0);
if (pnum != num_buf)
free(pnum);
if (!res)
@@ -1042,8 +1061,7 @@ val vformat(val stream, val fmtstr, va_list vl)
output_num:
{
val res = vformat_num(stream, pnum, width, left,
- precision ? 0 : zeropad,
- precision ? precision : 1);
+ zeropad, precision, sign);
if (pnum != num_buf)
free(pnum);
if (!res)