From a2a0ee42bae0fb615b2e9d3666090ce3d21031a0 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 16 Aug 2021 06:54:04 -0700 Subject: format: bug: sign not reset before each conversion. For instance, this bad output is produced: (pic "+0####.## <<<<<" 123 1) -> "+00123.00 +1 " The second argument should not have any leading + sign. * stream.c (formatv): For each new conversion specifier introduced by ~, reset the sign variable to zero also. That's the semantic change here, occluded by the fact that I'm rearranging the declaration of the variables, adding comments, and condensing the assignments while also getting them into the same order as the declarations, in order that this sort of bug does not creep in in the future, should another such variable be added. * tests/018/format.tl: Adding correct version of above test case. --- stream.c | 19 ++++++++----------- tests/018/format.tl | 4 ++++ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/stream.c b/stream.c index 3f2cafb3..56100bd9 100644 --- a/stream.c +++ b/stream.c @@ -3337,12 +3337,14 @@ val formatv(val stream_in, val fmtstr, struct args *al) enum { vf_init, vf_width, vf_digits, vf_star, vf_precision, vf_spec } state = vf_init, saved_state = vf_init; - int width = 0, precision = 0, precision_p = 0, digits = 0, lt = 0, neg = 0; - enum align align = al_right; - int sign = 0, zeropad = 0, dfl_precision = 0; - int dfl_digits = 0, print_base = 0; cnum value; cnum arg_ix = 0; + /* conversion variables that are reset before for each conversion */ + int width = 0, precision = 0, precision_p = 0, digits = 0, lt = 0, neg = 0; + int sign = 0, zeropad = 0; + enum align align = al_right; + /* conversion variables that persist across conversions */ + int dfl_precision = 0, dfl_digits = 0, print_base = 0; for (;;) { val obj; @@ -3357,14 +3359,9 @@ val formatv(val stream_in, val fmtstr, struct args *al) break; case '~': state = vf_width; - width = 0; + width = precision = precision_p = 0; + digits = lt = neg = sign = zeropad = 0; align = al_right; - zeropad = 0; - precision = 0; - precision_p = 0; - digits = 0; - lt = 0; - neg = 0; continue; default: put_char(chr(ch), stream); diff --git a/tests/018/format.tl b/tests/018/format.tl index 1b161936..0496d51f 100644 --- a/tests/018/format.tl +++ b/tests/018/format.tl @@ -227,3 +227,7 @@ (let ((a 2) (b "###") (c 13.5)) (pic `abc@(+ a a)###.##@b>>>>` c "x")) "abc4 13.50### x") + +(test + (pic "+0####.## <<<<<" 123 1) + "+00123.00 1 ") -- cgit v1.2.3