replay CL 19916 and CL 19913 now that the build can handle them
TBR=r
OCL=19924
CL=19934
diff --git a/src/lib/fmt/format.go b/src/lib/fmt/format.go
index 058c619..64d6c9b 100644
--- a/src/lib/fmt/format.go
+++ b/src/lib/fmt/format.go
@@ -4,7 +4,9 @@
package fmt
-import "strconv"
+import (
+ "strconv";
+)
/*
Raw formatter. See print.go for a more palatable interface.
@@ -39,11 +41,22 @@
wid_present bool;
prec int;
prec_present bool;
+ // flags
+ minus bool;
+ plus bool;
+ sharp bool;
+ space bool;
+ zero bool;
}
func (f *Fmt) clearflags() {
f.wid_present = false;
f.prec_present = false;
+ f.minus = false;
+ f.plus = false;
+ f.sharp = false;
+ f.space = false;
+ f.zero = false;
}
func (f *Fmt) clearbuf() {
@@ -101,24 +114,28 @@
return f;
}
-// append s to buf, padded on left (w > 0) or right (w < 0)
+// append s to buf, padded on left (w > 0) or right (w < 0 or f.minus)
// padding is in bytes, not characters (agrees with ANSIC C, not Plan 9 C)
func (f *Fmt) pad(s string) {
if f.wid_present && f.wid != 0 {
- left := true;
+ left := !f.minus;
w := f.wid;
if w < 0 {
left = false;
w = -w;
}
w -= len(s);
+ padchar := byte(' ');
+ if left && f.zero {
+ padchar = '0';
+ }
if w > 0 {
if w > NByte {
w = NByte;
}
buf := new([]byte, w);
for i := 0; i < w; i++ {
- buf[i] = ' ';
+ buf[i] = padchar;
}
if left {
s = string(buf) + s;
@@ -163,16 +180,35 @@
if negative {
a = -a;
}
- i := putint(&buf, NByte-1, uint64(base), uint64(a), digits);
+
+ // two ways to ask for extra leading zero digits: %.3d or %03d.
+ // apparently the first cancels the second.
+ prec := 0;
if f.prec_present {
- for i > 0 && f.prec > (NByte-1-i) {
- buf[i] = '0';
- i--;
+ prec = f.prec;
+ f.zero = false;
+ } else if f.zero && f.wid_present && !f.minus && f.wid > 0{
+ prec = f.wid;
+ if negative || f.plus || f.space {
+ prec--; // leave room for sign
}
}
+
+ i := putint(&buf, NByte-1, uint64(base), uint64(a), digits);
+ for i > 0 && prec > (NByte-1-i) {
+ buf[i] = '0';
+ i--;
+ }
+
if negative {
buf[i] = '-';
i--;
+ } else if f.plus {
+ buf[i] = '+';
+ i--;
+ } else if f.space {
+ buf[i] = ' ';
+ i--;
}
return string(buf)[i+1:NByte];
}
@@ -334,6 +370,44 @@
return f;
}
+// hexadecimal string
+func (f *Fmt) sx(s string) *Fmt {
+ t := "";
+ for i := 0; i < len(s); i++ {
+ v := s[i];
+ t += string(ldigits[v>>4]);
+ t += string(ldigits[v&0xF]);
+ }
+ f.pad(t);
+ f.clearflags();
+ return f;
+}
+
+func (f *Fmt) sX(s string) *Fmt {
+ t := "";
+ for i := 0; i < len(s); i++ {
+ v := s[i];
+ t += string(udigits[v>>4]);
+ t += string(udigits[v&0xF]);
+ }
+ f.pad(t);
+ f.clearflags();
+ return f;
+}
+
+// quoted string
+func (f *Fmt) q(s string) *Fmt {
+ var quoted string;
+ if f.sharp && strconv.CanBackquote(s) {
+ quoted = "`"+s+"`";
+ } else {
+ quoted = strconv.Quote(s);
+ }
+ f.pad(quoted);
+ f.clearflags();
+ return f;
+}
+
// floating-point
func Prec(f *Fmt, def int) int {
@@ -370,7 +444,7 @@
// cannot defer to float64 versions
// because it will get rounding wrong in corner cases.
func (f *Fmt) e32(a float32) *Fmt {
- return FmtString(f, strconv.ftoa32(a, 'e', Prec(f, -1)));
+ return FmtString(f, strconv.ftoa32(a, 'e', Prec(f, 6)));
}
func (f *Fmt) f32(a float32) *Fmt {