diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2014-03-05 01:31:46 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2014-03-05 01:43:17 -0800 |
commit | b6b7464882986fc24d7e3e6f37b694593d1097a1 (patch) | |
tree | 023d4ae7cb67b099c882526f9952e089dde92dcc /stream.c | |
parent | 67ac7a217bdfd6e4a813cc6caa68a75fb754e28b (diff) | |
download | txr-b6b7464882986fc24d7e3e6f37b694593d1097a1.tar.gz txr-b6b7464882986fc24d7e3e6f37b694593d1097a1.tar.bz2 txr-b6b7464882986fc24d7e3e6f37b694593d1097a1.zip |
* stream.c (vformat): Fix broken parsing of parameteric width and
precision (i.e. given by *). The simplest way to do this is to add a
state vf_star which is similar to vf_digits, and reuses much of the
logic via a goto. Fixing forgotten --fmt (push back char) when moving
from vf_precision to vf_spec state due to unhandled character.
Also, allowing a leading zero before a precision given as *
so that computed precisions can be combined with zero padding.
* txr.1: Documented leading zero better so it is clear it
combines with *. Restructured documentation.
Diffstat (limited to 'stream.c')
-rw-r--r-- | stream.c | 22 |
1 files changed, 13 insertions, 9 deletions
@@ -1511,7 +1511,7 @@ val vformat(val stream, val fmtstr, va_list vl) { const wchar_t *fmt = c_str(fmtstr); enum { - vf_init, vf_width, vf_digits, vf_precision, vf_spec + 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; int left = 0, sign = 0, zeropad = 0; @@ -1561,9 +1561,8 @@ val vformat(val stream, val fmtstr, va_list vl) digits = ch - '0'; continue; case '*': - obj = va_arg(vl, val); - width = c_num(obj); - state = vf_precision; + saved_state = state; + state = vf_star; continue; default: state = vf_spec; @@ -1575,7 +1574,7 @@ val vformat(val stream, val fmtstr, va_list vl) switch (ch) { case '0': zeropad = 1; - /* fallthrough */ + continue; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': saved_state = state; @@ -1586,13 +1585,12 @@ val vformat(val stream, val fmtstr, va_list vl) sign = ch; continue; case '*': - obj = va_arg(vl, val); - width = c_num(obj); - precision = vf_precision; - precision_p = 1; + saved_state = state; + state = vf_star; continue; default: state = vf_spec; + --fmt; continue; } break; @@ -1605,6 +1603,7 @@ val vformat(val stream, val fmtstr, va_list vl) goto toobig; continue; default: + do_digits: switch (saved_state) { case vf_width: if (width < 0) { @@ -1631,6 +1630,11 @@ val vformat(val stream, val fmtstr, va_list vl) } } break; + case vf_star: + obj = va_arg(vl, val); + digits = c_num(obj); + goto do_digits; + break; case vf_spec: state = vf_init; switch (ch) { |