aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/fmt
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2015-01-15 00:27:56 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2015-01-15 00:27:56 +0000
commitf8d9fa9e80b57f89e7877ce6cad8a3464879009b (patch)
tree58a1724fee16d2b03c65678c4dd9b50bb97137a9 /libgo/go/fmt
parent6bd3f109d8d8fa58eeccd6b3504721b4f20c00c2 (diff)
downloadgcc-f8d9fa9e80b57f89e7877ce6cad8a3464879009b.zip
gcc-f8d9fa9e80b57f89e7877ce6cad8a3464879009b.tar.gz
gcc-f8d9fa9e80b57f89e7877ce6cad8a3464879009b.tar.bz2
libgo, compiler: Upgrade libgo to Go 1.4, except for runtime.
This upgrades all of libgo other than the runtime package to the Go 1.4 release. In Go 1.4 much of the runtime was rewritten into Go. Merging that code will take more time and will not change the API, so I'm putting it off for now. There are a few runtime changes anyhow, to accomodate other packages that rely on minor modifications to the runtime support. The compiler changes slightly to add a one-bit flag to each type descriptor kind that is stored directly in an interface, which for gccgo is currently only pointer types. Another one-bit flag (gcprog) is reserved because it is used by the gc compiler, but gccgo does not currently use it. There is another error check in the compiler since I ran across it during testing. gotools/: * Makefile.am (go_cmd_go_files): Sort entries. Add generate.go. * Makefile.in: Rebuild. From-SVN: r219627
Diffstat (limited to 'libgo/go/fmt')
-rw-r--r--libgo/go/fmt/doc.go47
-rw-r--r--libgo/go/fmt/fmt_test.go197
-rw-r--r--libgo/go/fmt/format.go84
-rw-r--r--libgo/go/fmt/print.go226
-rw-r--r--libgo/go/fmt/scan.go1
-rw-r--r--libgo/go/fmt/scan_test.go32
6 files changed, 431 insertions, 156 deletions
diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go
index 02642d6..ee54463 100644
--- a/libgo/go/fmt/doc.go
+++ b/libgo/go/fmt/doc.go
@@ -13,7 +13,7 @@
The verbs:
General:
- %v the value in a default format.
+ %v the value in a default format
when printing structs, the plus flag (%+v) adds field names
%#v a Go-syntax representation of the value
%T a Go-syntax representation of the type of the value
@@ -38,8 +38,8 @@
%E scientific notation, e.g. -1234.456E+78
%f decimal point but no exponent, e.g. 123.456
%F synonym for %f
- %g whichever of %e or %f produces more compact output
- %G whichever of %E or %f produces more compact output
+ %g %e for large exponents, %f otherwise
+ %G %E for large exponents, %F otherwise
String and slice of bytes:
%s the uninterpreted bytes of the string or slice
%q a double-quoted string safely escaped with Go syntax
@@ -51,6 +51,21 @@
There is no 'u' flag. Integers are printed unsigned if they have unsigned type.
Similarly, there is no need to specify the size of the operand (int8, int64).
+ The default format for %v is:
+ bool: %t
+ int, int8 etc.: %d
+ uint, uint8 etc.: %d, %x if printed with %#v
+ float32, complex64, etc: %g
+ string: %s
+ chan: %p
+ pointer: %p
+ For compound objects, the elements are printed using these rules, recursively,
+ laid out like this:
+ struct: {field0 field1 ...}
+ array, slice: [elem0 elem1 ...]
+ maps: map[key1:value1 key2:value2]
+ pointer to above: &{}, &[], &map[]
+
Width is specified by an optional decimal number immediately following the verb.
If absent, the width is whatever is necessary to represent the value.
Precision is specified after the (optional) width by a period followed by a
@@ -63,16 +78,20 @@
%9.2f width 9, precision 2
%9.f width 9, precision 0
- Width and precision are measured in units of Unicode code points.
- (This differs from C's printf where the units are numbers
- of bytes.) Either or both of the flags may be replaced with the
- character '*', causing their values to be obtained from the next
- operand, which must be of type int.
+ Width and precision are measured in units of Unicode code points,
+ that is, runes. (This differs from C's printf where the
+ units are always measured in bytes.) Either or both of the flags
+ may be replaced with the character '*', causing their values to be
+ obtained from the next operand, which must be of type int.
- For most values, width is the minimum number of characters to output,
+ For most values, width is the minimum number of runes to output,
padding the formatted form with spaces if necessary.
- For strings, precision is the maximum number of characters to output,
- truncating if necessary.
+
+ For strings, byte slices and byte arrays, however, precision
+ limits the length of the input to be formatted (not the size of
+ the output), truncating if necessary. Normally it is measured in
+ runes, but for these types when formatted with the %x or %X format
+ it is measured in bytes.
For floating-point values, width sets the minimum width of the field and
precision sets the number of places after the decimal, if appropriate,
@@ -147,6 +166,10 @@
func (x X) String() string { return Sprintf("<%s>", x) }
convert the value before recurring:
func (x X) String() string { return Sprintf("<%s>", string(x)) }
+ Infinite recursion can also be triggered by self-referential data
+ structures, such as a slice that contains itself as an element, if
+ that type has a String method. Such pathologies are rare, however,
+ and the package does not protect against them.
Explicit argument indexes:
@@ -160,7 +183,7 @@
For example,
fmt.Sprintf("%[2]d %[1]d\n", 11, 22)
- will yield "22, 11", while
+ will yield "22 11", while
fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6),
equivalent to
fmt.Sprintf("%6.2f", 12.0),
diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go
index 8e69231..ccd8090 100644
--- a/libgo/go/fmt/fmt_test.go
+++ b/libgo/go/fmt/fmt_test.go
@@ -108,6 +108,20 @@ func (p *P) String() string {
var barray = [5]renamedUint8{1, 2, 3, 4, 5}
var bslice = barray[:]
+type byteStringer byte
+
+func (byteStringer) String() string { return "X" }
+
+var byteStringerSlice = []byteStringer{97, 98, 99, 100}
+
+type byteFormatter byte
+
+func (byteFormatter) Format(f State, _ rune) {
+ Fprint(f, "X")
+}
+
+var byteFormatterSlice = []byteFormatter{97, 98, 99, 100}
+
var b byte
var fmtTests = []struct {
@@ -125,13 +139,17 @@ var fmtTests = []struct {
{"%x", "xyz", "78797a"},
{"%X", "xyz", "78797A"},
{"%q", "abc", `"abc"`},
+ {"%#x", []byte("abc\xff"), "0x616263ff"},
+ {"%#X", []byte("abc\xff"), "0X616263FF"},
+ {"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"},
+ {"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"},
// basic bytes
{"%s", []byte("abc"), "abc"},
{"%x", []byte("abc"), "616263"},
{"% x", []byte("abc\xff"), "61 62 63 ff"},
- {"%#x", []byte("abc\xff"), "0x610x620x630xff"},
- {"%#X", []byte("abc\xff"), "0X610X620X630XFF"},
+ {"%#x", []byte("abc\xff"), "0x616263ff"},
+ {"%#X", []byte("abc\xff"), "0X616263FF"},
{"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"},
{"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"},
{"% X", []byte("abc\xff"), "61 62 63 FF"},
@@ -176,9 +194,18 @@ var fmtTests = []struct {
{"%.5s", "日本語日本語", "日本語日本"},
{"%.5s", []byte("日本語日本語"), "日本語日本"},
{"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`},
+ {"%.5x", "abcdefghijklmnopqrstuvwxyz", `6162636465`},
+ {"%.5q", []byte("abcdefghijklmnopqrstuvwxyz"), `"abcde"`},
+ {"%.5x", []byte("abcdefghijklmnopqrstuvwxyz"), `6162636465`},
{"%.3q", "日本語日本語", `"日本語"`},
{"%.3q", []byte("日本語日本語"), `"日本語"`},
+ {"%.1q", "日本語", `"日"`},
+ {"%.1q", []byte("日本語"), `"日"`},
+ {"%.1x", "日本語", `e6`},
+ {"%.1X", []byte("日本語"), `E6`},
{"%10.1q", "日本語日本語", ` "日"`},
+ {"%3c", '⌘', " ⌘"},
+ {"%5q", '\u2026', ` '…'`},
{"%10v", nil, " <nil>"},
{"%-10v", nil, "<nil> "},
@@ -379,7 +406,7 @@ var fmtTests = []struct {
{"%s", I(23), `<23>`},
{"%q", I(23), `"<23>"`},
{"%x", I(23), `3c32333e`},
- {"%#x", I(23), `0x3c0x320x330x3e`},
+ {"%#x", I(23), `0x3c32333e`},
{"%# x", I(23), `0x3c 0x32 0x33 0x3e`},
{"%d", I(23), `23`}, // Stringer applies only to string formats.
@@ -623,6 +650,21 @@ var fmtTests = []struct {
{"%+010.2f", -104.66 + 440.51i, "(-000104.66+000440.51i)"},
{"%+010.2f", +104.66 - 440.51i, "(+000104.66-000440.51i)"},
{"%+010.2f", -104.66 - 440.51i, "(-000104.66-000440.51i)"},
+
+ // []T where type T is a byte with a Stringer method.
+ {"%v", byteStringerSlice, "[X X X X]"},
+ {"%s", byteStringerSlice, "abcd"},
+ {"%q", byteStringerSlice, "\"abcd\""},
+ {"%x", byteStringerSlice, "61626364"},
+ {"%#v", byteStringerSlice, "[]fmt_test.byteStringer{0x61, 0x62, 0x63, 0x64}"},
+
+ // And the same for Formatter.
+ {"%v", byteFormatterSlice, "[X X X X]"},
+ {"%s", byteFormatterSlice, "abcd"},
+ {"%q", byteFormatterSlice, "\"abcd\""},
+ {"%x", byteFormatterSlice, "61626364"},
+ // This next case seems wrong, but the docs say the Formatter wins here.
+ {"%#v", byteFormatterSlice, "[]fmt_test.byteFormatter{X, X, X, X}"},
}
// zeroFill generates zero-filled strings of the specified width. The length
@@ -672,7 +714,7 @@ func TestSprintf(t *testing.T) {
// thing as if done by hand with two singleton prints.
func TestComplexFormatting(t *testing.T) {
var yesNo = []bool{true, false}
- var signs = []float64{1, 0, -1}
+ var values = []float64{1, 0, -1, math.Inf(1), math.Inf(-1), math.NaN()}
for _, plus := range yesNo {
for _, zero := range yesNo {
for _, space := range yesNo {
@@ -697,10 +739,10 @@ func TestComplexFormatting(t *testing.T) {
imagFmt += "+"
imagFmt += "10.2"
imagFmt += string(char)
- for _, realSign := range signs {
- for _, imagSign := range signs {
- one := Sprintf(realFmt, complex(realSign, imagSign))
- two := Sprintf("("+realFmt+imagFmt+"i)", realSign, imagSign)
+ for _, realValue := range values {
+ for _, imagValue := range values {
+ one := Sprintf(realFmt, complex(realValue, imagValue))
+ two := Sprintf("("+realFmt+imagFmt+"i)", realValue, imagValue)
if one != two {
t.Error(f, one, two)
}
@@ -819,7 +861,25 @@ func BenchmarkManyArgs(b *testing.B) {
})
}
+func BenchmarkFprintInt(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ Fprint(&buf, 123456)
+ }
+}
+
+func BenchmarkFprintIntNoAlloc(b *testing.B) {
+ var x interface{} = 123456
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ Fprint(&buf, x)
+ }
+}
+
var mallocBuf bytes.Buffer
+var mallocPointer *int // A pointer so we know the interface value won't allocate.
// gccgo numbers are different because gccgo does not have escape
// analysis yet.
@@ -833,11 +893,13 @@ var mallocTest = []struct {
{5, `Sprintf("%x")`, func() { Sprintf("%x", 7) }},
{5, `Sprintf("%s")`, func() { Sprintf("%s", "hello") }},
{5, `Sprintf("%x %x")`, func() { Sprintf("%x %x", 7, 112) }},
- // For %g we use a float32, not float64, to guarantee passing the argument
- // does not need to allocate memory to store the result in a pointer-sized word.
- {20, `Sprintf("%g")`, func() { Sprintf("%g", float32(3.14159)) }},
- {5, `Fprintf(buf, "%x %x %x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x %x %x", 7, 8, 9) }},
+ {20, `Sprintf("%g")`, func() { Sprintf("%g", float32(3.14159)) }}, // TODO: Can this be 1?
{5, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }},
+ // If the interface value doesn't need to allocate, amortized allocation overhead should be zero.
+ {5, `Fprintf(buf, "%x %x %x")`, func() {
+ mallocBuf.Reset()
+ Fprintf(&mallocBuf, "%x %x %x", mallocPointer, mallocPointer, mallocPointer)
+ }},
}
var _ bytes.Buffer
@@ -859,7 +921,7 @@ func TestCountMallocs(t *testing.T) {
type flagPrinter struct{}
-func (*flagPrinter) Format(f State, c rune) {
+func (flagPrinter) Format(f State, c rune) {
s := "%"
for i := 0; i < 128; i++ {
if f.Flag(i) {
@@ -905,11 +967,12 @@ func TestFlagParser(t *testing.T) {
}
func TestStructPrinter(t *testing.T) {
- var s struct {
+ type T struct {
a string
b string
c int
}
+ var s T
s.a = "abc"
s.b = "def"
s.c = 123
@@ -919,15 +982,38 @@ func TestStructPrinter(t *testing.T) {
}{
{"%v", "{abc def 123}"},
{"%+v", "{a:abc b:def c:123}"},
+ {"%#v", `fmt_test.T{a:"abc", b:"def", c:123}`},
}
for _, tt := range tests {
out := Sprintf(tt.fmt, s)
if out != tt.out {
- t.Errorf("Sprintf(%q, &s) = %q, want %q", tt.fmt, out, tt.out)
+ t.Errorf("Sprintf(%q, s) = %#q, want %#q", tt.fmt, out, tt.out)
+ }
+ // The same but with a pointer.
+ out = Sprintf(tt.fmt, &s)
+ if out != "&"+tt.out {
+ t.Errorf("Sprintf(%q, &s) = %#q, want %#q", tt.fmt, out, "&"+tt.out)
}
}
}
+func TestSlicePrinter(t *testing.T) {
+ slice := []int{}
+ s := Sprint(slice)
+ if s != "[]" {
+ t.Errorf("empty slice printed as %q not %q", s, "[]")
+ }
+ slice = []int{1, 2, 3}
+ s = Sprint(slice)
+ if s != "[1 2 3]" {
+ t.Errorf("slice: got %q expected %q", s, "[1 2 3]")
+ }
+ s = Sprint(&slice)
+ if s != "&[1 2 3]" {
+ t.Errorf("&slice: got %q expected %q", s, "&[1 2 3]")
+ }
+}
+
// presentInMap checks map printing using substrings so we don't depend on the
// print order.
func presentInMap(s string, a []string, t *testing.T) {
@@ -954,6 +1040,12 @@ func TestMapPrinter(t *testing.T) {
a := []string{"1:one", "2:two", "3:three"}
presentInMap(Sprintf("%v", m1), a, t)
presentInMap(Sprint(m1), a, t)
+ // Pointer to map prints the same but with initial &.
+ if !strings.HasPrefix(Sprint(&m1), "&") {
+ t.Errorf("no initial & for address of map")
+ }
+ presentInMap(Sprintf("%v", &m1), a, t)
+ presentInMap(Sprint(&m1), a, t)
}
func TestEmptyMap(t *testing.T) {
@@ -1084,10 +1176,10 @@ var panictests = []struct {
}
func TestPanics(t *testing.T) {
- for _, tt := range panictests {
+ for i, tt := range panictests {
s := Sprintf(tt.fmt, tt.in)
if s != tt.out {
- t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
+ t.Errorf("%d: %q: got %q expected %q", i, tt.fmt, s, tt.out)
}
}
}
@@ -1147,3 +1239,74 @@ func TestNilDoesNotBecomeTyped(t *testing.T) {
t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got)
}
}
+
+var formatterFlagTests = []struct {
+ in string
+ val interface{}
+ out string
+}{
+ // scalar values with the (unused by fmt) 'a' verb.
+ {"%a", flagPrinter{}, "[%a]"},
+ {"%-a", flagPrinter{}, "[%-a]"},
+ {"%+a", flagPrinter{}, "[%+a]"},
+ {"%#a", flagPrinter{}, "[%#a]"},
+ {"% a", flagPrinter{}, "[% a]"},
+ {"%0a", flagPrinter{}, "[%0a]"},
+ {"%1.2a", flagPrinter{}, "[%1.2a]"},
+ {"%-1.2a", flagPrinter{}, "[%-1.2a]"},
+ {"%+1.2a", flagPrinter{}, "[%+1.2a]"},
+ {"%-+1.2a", flagPrinter{}, "[%+-1.2a]"},
+ {"%-+1.2abc", flagPrinter{}, "[%+-1.2a]bc"},
+ {"%-1.2abc", flagPrinter{}, "[%-1.2a]bc"},
+
+ // composite values with the 'a' verb
+ {"%a", [1]flagPrinter{}, "[[%a]]"},
+ {"%-a", [1]flagPrinter{}, "[[%-a]]"},
+ {"%+a", [1]flagPrinter{}, "[[%+a]]"},
+ {"%#a", [1]flagPrinter{}, "[[%#a]]"},
+ {"% a", [1]flagPrinter{}, "[[% a]]"},
+ {"%0a", [1]flagPrinter{}, "[[%0a]]"},
+ {"%1.2a", [1]flagPrinter{}, "[[%1.2a]]"},
+ {"%-1.2a", [1]flagPrinter{}, "[[%-1.2a]]"},
+ {"%+1.2a", [1]flagPrinter{}, "[[%+1.2a]]"},
+ {"%-+1.2a", [1]flagPrinter{}, "[[%+-1.2a]]"},
+ {"%-+1.2abc", [1]flagPrinter{}, "[[%+-1.2a]]bc"},
+ {"%-1.2abc", [1]flagPrinter{}, "[[%-1.2a]]bc"},
+
+ // simple values with the 'v' verb
+ {"%v", flagPrinter{}, "[%v]"},
+ {"%-v", flagPrinter{}, "[%-v]"},
+ {"%+v", flagPrinter{}, "[%+v]"},
+ {"%#v", flagPrinter{}, "[%#v]"},
+ {"% v", flagPrinter{}, "[% v]"},
+ {"%0v", flagPrinter{}, "[%0v]"},
+ {"%1.2v", flagPrinter{}, "[%1.2v]"},
+ {"%-1.2v", flagPrinter{}, "[%-1.2v]"},
+ {"%+1.2v", flagPrinter{}, "[%+1.2v]"},
+ {"%-+1.2v", flagPrinter{}, "[%+-1.2v]"},
+ {"%-+1.2vbc", flagPrinter{}, "[%+-1.2v]bc"},
+ {"%-1.2vbc", flagPrinter{}, "[%-1.2v]bc"},
+
+ // composite values with the 'v' verb.
+ {"%v", [1]flagPrinter{}, "[[%v]]"},
+ {"%-v", [1]flagPrinter{}, "[[%-v]]"},
+ {"%+v", [1]flagPrinter{}, "[[%+v]]"},
+ {"%#v", [1]flagPrinter{}, "[1]fmt_test.flagPrinter{[%#v]}"},
+ {"% v", [1]flagPrinter{}, "[[% v]]"},
+ {"%0v", [1]flagPrinter{}, "[[%0v]]"},
+ {"%1.2v", [1]flagPrinter{}, "[[%1.2v]]"},
+ {"%-1.2v", [1]flagPrinter{}, "[[%-1.2v]]"},
+ {"%+1.2v", [1]flagPrinter{}, "[[%+1.2v]]"},
+ {"%-+1.2v", [1]flagPrinter{}, "[[%+-1.2v]]"},
+ {"%-+1.2vbc", [1]flagPrinter{}, "[[%+-1.2v]]bc"},
+ {"%-1.2vbc", [1]flagPrinter{}, "[[%-1.2v]]bc"},
+}
+
+func TestFormatterFlags(t *testing.T) {
+ for _, tt := range formatterFlagTests {
+ s := Sprintf(tt.in, tt.val)
+ if s != tt.out {
+ t.Errorf("Sprintf(%q, %T) = %q, want %q", tt.in, tt.val, s, tt.out)
+ }
+ }
+}
diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go
index a89c542..4d97d14 100644
--- a/libgo/go/fmt/format.go
+++ b/libgo/go/fmt/format.go
@@ -34,15 +34,8 @@ func init() {
}
}
-// A fmt is the raw formatter used by Printf etc.
-// It prints into a buffer that must be set up separately.
-type fmt struct {
- intbuf [nByte]byte
- buf *buffer
- // width, precision
- wid int
- prec int
- // flags
+// flags placed in a separate struct for easy clearing.
+type fmtFlags struct {
widPresent bool
precPresent bool
minus bool
@@ -52,20 +45,27 @@ type fmt struct {
unicode bool
uniQuote bool // Use 'x'= prefix for %U if printable.
zero bool
+
+ // For the formats %+v %#v, we set the plusV/sharpV flags
+ // and clear the plus/sharp flags since %+v and %#v are in effect
+ // different, flagless formats set at the top level.
+ plusV bool
+ sharpV bool
+}
+
+// A fmt is the raw formatter used by Printf etc.
+// It prints into a buffer that must be set up separately.
+type fmt struct {
+ intbuf [nByte]byte
+ buf *buffer
+ // width, precision
+ wid int
+ prec int
+ fmtFlags
}
func (f *fmt) clearflags() {
- f.wid = 0
- f.widPresent = false
- f.prec = 0
- f.precPresent = false
- f.minus = false
- f.plus = false
- f.sharp = false
- f.space = false
- f.unicode = false
- f.uniQuote = false
- f.zero = false
+ f.fmtFlags = fmtFlags{}
}
func (f *fmt) init(buf *buffer) {
@@ -114,7 +114,7 @@ func (f *fmt) pad(b []byte) {
f.buf.Write(b)
return
}
- padding, left, right := f.computePadding(len(b))
+ padding, left, right := f.computePadding(utf8.RuneCount(b))
if left > 0 {
f.writePadding(left, padding)
}
@@ -199,10 +199,36 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
// block but it's not worth the duplication, so ua has 64 bits.
i := len(buf)
ua := uint64(a)
- for ua >= base {
- i--
- buf[i] = digits[ua%base]
- ua /= base
+ // use constants for the division and modulo for more efficient code.
+ // switch cases ordered by popularity.
+ switch base {
+ case 10:
+ for ua >= 10 {
+ i--
+ next := ua / 10
+ buf[i] = byte('0' + ua - next*10)
+ ua = next
+ }
+ case 16:
+ for ua >= 16 {
+ i--
+ buf[i] = digits[ua&0xF]
+ ua >>= 4
+ }
+ case 8:
+ for ua >= 8 {
+ i--
+ buf[i] = byte('0' + ua&7)
+ ua >>= 3
+ }
+ case 2:
+ for ua >= 2 {
+ i--
+ buf[i] = byte('0' + ua&1)
+ ua >>= 1
+ }
+ default:
+ panic("fmt: unknown base; can't happen")
}
i--
buf[i] = digits[ua]
@@ -298,7 +324,7 @@ func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
if i > 0 && f.space {
buf = append(buf, ' ')
}
- if f.sharp {
+ if f.sharp && (f.space || i == 0) {
buf = append(buf, '0', x)
}
var c byte
@@ -314,11 +340,17 @@ func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
// fmt_sx formats a string as a hexadecimal encoding of its bytes.
func (f *fmt) fmt_sx(s, digits string) {
+ if f.precPresent && f.prec < len(s) {
+ s = s[:f.prec]
+ }
f.fmt_sbx(s, nil, digits)
}
// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
func (f *fmt) fmt_bx(b []byte, digits string) {
+ if f.precPresent && f.prec < len(b) {
+ b = b[:f.prec]
+ }
f.fmt_sbx("", b, digits)
}
diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go
index 302661f..59a30d2 100644
--- a/libgo/go/fmt/print.go
+++ b/libgo/go/fmt/print.go
@@ -128,7 +128,7 @@ var ppFree = sync.Pool{
New: func() interface{} { return new(pp) },
}
-// newPrinter allocates a new pp struct or grab a cached one.
+// newPrinter allocates a new pp struct or grabs a cached one.
func newPrinter() *pp {
p := ppFree.Get().(*pp)
p.panicking = false
@@ -297,13 +297,13 @@ func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
return
}
-func (p *pp) unknownType(v interface{}) {
- if v == nil {
+func (p *pp) unknownType(v reflect.Value) {
+ if !v.IsValid() {
p.buf.Write(nilAngleBytes)
return
}
p.buf.WriteByte('?')
- p.buf.WriteString(reflect.TypeOf(v).String())
+ p.buf.WriteString(v.Type().String())
p.buf.WriteByte('?')
}
@@ -317,11 +317,11 @@ func (p *pp) badVerb(verb rune) {
case p.arg != nil:
p.buf.WriteString(reflect.TypeOf(p.arg).String())
p.add('=')
- p.printArg(p.arg, 'v', false, false, 0)
+ p.printArg(p.arg, 'v', 0)
case p.value.IsValid():
p.buf.WriteString(p.value.Type().String())
p.add('=')
- p.printValue(p.value, 'v', false, false, 0)
+ p.printValue(p.value, 'v', 0)
default:
p.buf.Write(nilAngleBytes)
}
@@ -406,7 +406,7 @@ func (p *pp) fmtUnicode(v int64) {
p.fmt.sharp = sharp
}
-func (p *pp) fmtUint64(v uint64, verb rune, goSyntax bool) {
+func (p *pp) fmtUint64(v uint64, verb rune) {
switch verb {
case 'b':
p.fmt.integer(int64(v), 2, unsigned, ldigits)
@@ -415,7 +415,7 @@ func (p *pp) fmtUint64(v uint64, verb rune, goSyntax bool) {
case 'd':
p.fmt.integer(int64(v), 10, unsigned, ldigits)
case 'v':
- if goSyntax {
+ if p.fmt.sharpV {
p.fmt0x64(v, true)
} else {
p.fmt.integer(int64(v), 10, unsigned, ldigits)
@@ -499,10 +499,10 @@ func (p *pp) fmtComplex128(v complex128, verb rune) {
}
}
-func (p *pp) fmtString(v string, verb rune, goSyntax bool) {
+func (p *pp) fmtString(v string, verb rune) {
switch verb {
case 'v':
- if goSyntax {
+ if p.fmt.sharpV {
p.fmt.fmt_q(v)
} else {
p.fmt.fmt_s(v)
@@ -520,9 +520,9 @@ func (p *pp) fmtString(v string, verb rune, goSyntax bool) {
}
}
-func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, depth int) {
+func (p *pp) fmtBytes(v []byte, verb rune, typ reflect.Type, depth int) {
if verb == 'v' || verb == 'd' {
- if goSyntax {
+ if p.fmt.sharpV {
if v == nil {
if typ == nil {
p.buf.WriteString("[]byte(nil)")
@@ -543,15 +543,15 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, dept
}
for i, c := range v {
if i > 0 {
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.Write(commaSpaceBytes)
} else {
p.buf.WriteByte(' ')
}
}
- p.printArg(c, 'v', p.fmt.plus, goSyntax, depth+1)
+ p.printArg(c, 'v', depth+1)
}
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteByte('}')
} else {
p.buf.WriteByte(']')
@@ -572,7 +572,7 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, dept
}
}
-func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
+func (p *pp) fmtPointer(value reflect.Value, verb rune) {
use0x64 := true
switch verb {
case 'p', 'v':
@@ -594,7 +594,7 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
return
}
- if goSyntax {
+ if p.fmt.sharpV {
p.add('(')
p.buf.WriteString(value.Type().String())
p.add(')')
@@ -611,7 +611,7 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
if use0x64 {
p.fmt0x64(uint64(u), !p.fmt.sharp)
} else {
- p.fmtUint64(uint64(u), verb, false)
+ p.fmtUint64(uint64(u), verb)
}
}
}
@@ -636,42 +636,65 @@ func (p *pp) catchPanic(arg interface{}, verb rune) {
// Nested panics; the recursion in printArg cannot succeed.
panic(err)
}
+ p.fmt.clearflags() // We are done, and for this output we want default behavior.
p.buf.Write(percentBangBytes)
p.add(verb)
p.buf.Write(panicBytes)
p.panicking = true
- p.printArg(err, 'v', false, false, 0)
+ p.printArg(err, 'v', 0)
p.panicking = false
p.buf.WriteByte(')')
}
}
-func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString, handled bool) {
+// clearSpecialFlags pushes %#v back into the regular flags and returns their old state.
+func (p *pp) clearSpecialFlags() (plusV, sharpV bool) {
+ plusV = p.fmt.plusV
+ if plusV {
+ p.fmt.plus = true
+ p.fmt.plusV = false
+ }
+ sharpV = p.fmt.sharpV
+ if sharpV {
+ p.fmt.sharp = true
+ p.fmt.sharpV = false
+ }
+ return
+}
+
+// restoreSpecialFlags, whose argument should be a call to clearSpecialFlags,
+// restores the setting of the plusV and sharpV flags.
+func (p *pp) restoreSpecialFlags(plusV, sharpV bool) {
+ if plusV {
+ p.fmt.plus = false
+ p.fmt.plusV = true
+ }
+ if sharpV {
+ p.fmt.sharp = false
+ p.fmt.sharpV = true
+ }
+}
+
+func (p *pp) handleMethods(verb rune, depth int) (handled bool) {
if p.erroring {
return
}
// Is it a Formatter?
if formatter, ok := p.arg.(Formatter); ok {
handled = true
- wasString = false
+ defer p.restoreSpecialFlags(p.clearSpecialFlags())
defer p.catchPanic(p.arg, verb)
formatter.Format(p, verb)
return
}
- // Must not touch flags before Formatter looks at them.
- if plus {
- p.fmt.plus = false
- }
// If we're doing Go syntax and the argument knows how to supply it, take care of it now.
- if goSyntax {
- p.fmt.sharp = false
+ if p.fmt.sharpV {
if stringer, ok := p.arg.(GoStringer); ok {
- wasString = false
handled = true
defer p.catchPanic(p.arg, verb)
// Print the result of GoString unadorned.
- p.fmtString(stringer.GoString(), 's', false)
+ p.fmt.fmt_s(stringer.GoString())
return
}
} else {
@@ -682,30 +705,27 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString
case 'v', 's', 'x', 'X', 'q':
// Is it an error or Stringer?
// The duplication in the bodies is necessary:
- // setting wasString and handled, and deferring catchPanic,
+ // setting handled and deferring catchPanic
// must happen before calling the method.
switch v := p.arg.(type) {
case error:
- wasString = false
handled = true
defer p.catchPanic(p.arg, verb)
- p.printArg(v.Error(), verb, plus, false, depth)
+ p.printArg(v.Error(), verb, depth)
return
case Stringer:
- wasString = false
handled = true
defer p.catchPanic(p.arg, verb)
- p.printArg(v.String(), verb, plus, false, depth)
+ p.printArg(v.String(), verb, depth)
return
}
}
}
- handled = false
- return
+ return false
}
-func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+func (p *pp) printArg(arg interface{}, verb rune, depth int) (wasString bool) {
p.arg = arg
p.value = reflect.Value{}
@@ -722,26 +742,13 @@ func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int
// %T (the value's type) and %p (its address) are special; we always do them first.
switch verb {
case 'T':
- p.printArg(reflect.TypeOf(arg).String(), 's', false, false, 0)
+ p.printArg(reflect.TypeOf(arg).String(), 's', 0)
return false
case 'p':
- p.fmtPointer(reflect.ValueOf(arg), verb, goSyntax)
+ p.fmtPointer(reflect.ValueOf(arg), verb)
return false
}
- // Clear flags for base formatters.
- // handleMethods needs them, so we must restore them later.
- // We could call handleMethods here and avoid this work, but
- // handleMethods is expensive enough to be worth delaying.
- oldPlus := p.fmt.plus
- oldSharp := p.fmt.sharp
- if plus {
- p.fmt.plus = false
- }
- if goSyntax {
- p.fmt.sharp = false
- }
-
// Some types can be done without reflection.
switch f := arg.(type) {
case bool:
@@ -765,40 +772,37 @@ func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int
case int64:
p.fmtInt64(f, verb)
case uint:
- p.fmtUint64(uint64(f), verb, goSyntax)
+ p.fmtUint64(uint64(f), verb)
case uint8:
- p.fmtUint64(uint64(f), verb, goSyntax)
+ p.fmtUint64(uint64(f), verb)
case uint16:
- p.fmtUint64(uint64(f), verb, goSyntax)
+ p.fmtUint64(uint64(f), verb)
case uint32:
- p.fmtUint64(uint64(f), verb, goSyntax)
+ p.fmtUint64(uint64(f), verb)
case uint64:
- p.fmtUint64(f, verb, goSyntax)
+ p.fmtUint64(f, verb)
case uintptr:
- p.fmtUint64(uint64(f), verb, goSyntax)
+ p.fmtUint64(uint64(f), verb)
case string:
- p.fmtString(f, verb, goSyntax)
+ p.fmtString(f, verb)
wasString = verb == 's' || verb == 'v'
case []byte:
- p.fmtBytes(f, verb, goSyntax, nil, depth)
+ p.fmtBytes(f, verb, nil, depth)
wasString = verb == 's'
default:
- // Restore flags in case handleMethods finds a Formatter.
- p.fmt.plus = oldPlus
- p.fmt.sharp = oldSharp
// If the type is not simple, it might have methods.
- if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
- return isString
+ if handled := p.handleMethods(verb, depth); handled {
+ return false
}
// Need to use reflection
- return p.printReflectValue(reflect.ValueOf(arg), verb, plus, goSyntax, depth)
+ return p.printReflectValue(reflect.ValueOf(arg), verb, depth)
}
p.arg = nil
return
}
// printValue is like printArg but starts with a reflect value, not an interface{} value.
-func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+func (p *pp) printValue(value reflect.Value, verb rune, depth int) (wasString bool) {
if !value.IsValid() {
if verb == 'T' || verb == 'v' {
p.buf.Write(nilAngleBytes)
@@ -812,10 +816,10 @@ func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, dep
// %T (the value's type) and %p (its address) are special; we always do them first.
switch verb {
case 'T':
- p.printArg(value.Type().String(), 's', false, false, 0)
+ p.printArg(value.Type().String(), 's', 0)
return false
case 'p':
- p.fmtPointer(value, verb, goSyntax)
+ p.fmtPointer(value, verb)
return false
}
@@ -825,16 +829,18 @@ func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, dep
if value.CanInterface() {
p.arg = value.Interface()
}
- if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
- return isString
+ if handled := p.handleMethods(verb, depth); handled {
+ return false
}
- return p.printReflectValue(value, verb, plus, goSyntax, depth)
+ return p.printReflectValue(value, verb, depth)
}
+var byteType = reflect.TypeOf(byte(0))
+
// printReflectValue is the fallback for both printArg and printValue.
// It uses reflect to print the value.
-func (p *pp) printReflectValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+func (p *pp) printReflectValue(value reflect.Value, verb rune, depth int) (wasString bool) {
oldValue := p.value
p.value = value
BigSwitch:
@@ -844,7 +850,7 @@ BigSwitch:
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p.fmtInt64(f.Int(), verb)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- p.fmtUint64(f.Uint(), verb, goSyntax)
+ p.fmtUint64(f.Uint(), verb)
case reflect.Float32, reflect.Float64:
if f.Type().Size() == 4 {
p.fmtFloat32(float32(f.Float()), verb)
@@ -858,9 +864,9 @@ BigSwitch:
p.fmtComplex128(f.Complex(), verb)
}
case reflect.String:
- p.fmtString(f.String(), verb, goSyntax)
+ p.fmtString(f.String(), verb)
case reflect.Map:
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteString(f.Type().String())
if f.IsNil() {
p.buf.WriteString("(nil)")
@@ -873,23 +879,23 @@ BigSwitch:
keys := f.MapKeys()
for i, key := range keys {
if i > 0 {
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.Write(commaSpaceBytes)
} else {
p.buf.WriteByte(' ')
}
}
- p.printValue(key, verb, plus, goSyntax, depth+1)
+ p.printValue(key, verb, depth+1)
p.buf.WriteByte(':')
- p.printValue(f.MapIndex(key), verb, plus, goSyntax, depth+1)
+ p.printValue(f.MapIndex(key), verb, depth+1)
}
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteByte('}')
} else {
p.buf.WriteByte(']')
}
case reflect.Struct:
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteString(value.Type().String())
}
p.add('{')
@@ -897,36 +903,40 @@ BigSwitch:
t := v.Type()
for i := 0; i < v.NumField(); i++ {
if i > 0 {
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.Write(commaSpaceBytes)
} else {
p.buf.WriteByte(' ')
}
}
- if plus || goSyntax {
+ if p.fmt.plusV || p.fmt.sharpV {
if f := t.Field(i); f.Name != "" {
p.buf.WriteString(f.Name)
p.buf.WriteByte(':')
}
}
- p.printValue(getField(v, i), verb, plus, goSyntax, depth+1)
+ p.printValue(getField(v, i), verb, depth+1)
}
p.buf.WriteByte('}')
case reflect.Interface:
value := f.Elem()
if !value.IsValid() {
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteString(f.Type().String())
p.buf.Write(nilParenBytes)
} else {
p.buf.Write(nilAngleBytes)
}
} else {
- wasString = p.printValue(value, verb, plus, goSyntax, depth+1)
+ wasString = p.printValue(value, verb, depth+1)
}
case reflect.Array, reflect.Slice:
- // Byte slices are special.
- if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 {
+ // Byte slices are special:
+ // - Handle []byte (== []uint8) with fmtBytes.
+ // - Handle []T, where T is a named byte type, with fmtBytes only
+ // for the s, q, an x verbs. For other verbs, T might be a
+ // Stringer, so we use printValue to print each element.
+ if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 && (typ.Elem() == byteType || verb == 's' || verb == 'q' || verb == 'x') {
var bytes []byte
if f.Kind() == reflect.Slice {
bytes = f.Bytes()
@@ -941,11 +951,11 @@ BigSwitch:
bytes[i] = byte(f.Index(i).Uint())
}
}
- p.fmtBytes(bytes, verb, goSyntax, typ, depth)
+ p.fmtBytes(bytes, verb, typ, depth)
wasString = verb == 's'
break
}
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteString(value.Type().String())
if f.Kind() == reflect.Slice && f.IsNil() {
p.buf.WriteString("(nil)")
@@ -957,15 +967,15 @@ BigSwitch:
}
for i := 0; i < f.Len(); i++ {
if i > 0 {
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.Write(commaSpaceBytes)
} else {
p.buf.WriteByte(' ')
}
}
- p.printValue(f.Index(i), verb, plus, goSyntax, depth+1)
+ p.printValue(f.Index(i), verb, depth+1)
}
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteByte('}')
} else {
p.buf.WriteByte(']')
@@ -978,17 +988,21 @@ BigSwitch:
switch a := f.Elem(); a.Kind() {
case reflect.Array, reflect.Slice:
p.buf.WriteByte('&')
- p.printValue(a, verb, plus, goSyntax, depth+1)
+ p.printValue(a, verb, depth+1)
break BigSwitch
case reflect.Struct:
p.buf.WriteByte('&')
- p.printValue(a, verb, plus, goSyntax, depth+1)
+ p.printValue(a, verb, depth+1)
+ break BigSwitch
+ case reflect.Map:
+ p.buf.WriteByte('&')
+ p.printValue(a, verb, depth+1)
break BigSwitch
}
}
fallthrough
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
- p.fmtPointer(value, verb, goSyntax)
+ p.fmtPointer(value, verb)
default:
p.unknownType(f)
}
@@ -1154,9 +1168,19 @@ func (p *pp) doPrintf(format string, a []interface{}) {
arg := a[argNum]
argNum++
- goSyntax := c == 'v' && p.fmt.sharp
- plus := c == 'v' && p.fmt.plus
- p.printArg(arg, c, plus, goSyntax, 0)
+ if c == 'v' {
+ if p.fmt.sharp {
+ // Go syntax. Set the flag in the fmt and clear the sharp flag.
+ p.fmt.sharp = false
+ p.fmt.sharpV = true
+ }
+ if p.fmt.plus {
+ // Struct-field syntax. Set the flag in the fmt and clear the plus flag.
+ p.fmt.plus = false
+ p.fmt.plusV = true
+ }
+ }
+ p.printArg(arg, c, 0)
}
// Check for extra arguments unless the call accessed the arguments
@@ -1170,7 +1194,7 @@ func (p *pp) doPrintf(format string, a []interface{}) {
p.buf.WriteString(reflect.TypeOf(arg).String())
p.buf.WriteByte('=')
}
- p.printArg(arg, 'v', false, false, 0)
+ p.printArg(arg, 'v', 0)
if argNum+1 < len(a) {
p.buf.Write(commaSpaceBytes)
}
@@ -1191,7 +1215,7 @@ func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) {
p.buf.WriteByte(' ')
}
}
- prevString = p.printArg(arg, 'v', false, false, 0)
+ prevString = p.printArg(arg, 'v', 0)
}
if addnewline {
p.buf.WriteByte('\n')
diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go
index 8a337e4..d7befea 100644
--- a/libgo/go/fmt/scan.go
+++ b/libgo/go/fmt/scan.go
@@ -360,6 +360,7 @@ func (r *readRune) ReadRune() (rr rune, size int, err error) {
}
if r.buf[0] < utf8.RuneSelf { // fast check for common ASCII case
rr = rune(r.buf[0])
+ size = 1 // Known to be 1.
return
}
var n int
diff --git a/libgo/go/fmt/scan_test.go b/libgo/go/fmt/scan_test.go
index d903f0c..541e12d 100644
--- a/libgo/go/fmt/scan_test.go
+++ b/libgo/go/fmt/scan_test.go
@@ -842,6 +842,38 @@ func TestLineByLineFscanf(t *testing.T) {
}
}
+// TestScanStateCount verifies the correct byte count is returned. Issue 8512.
+
+// runeScanner implements the Scanner interface for TestScanStateCount.
+type runeScanner struct {
+ rune rune
+ size int
+}
+
+func (rs *runeScanner) Scan(state ScanState, verb rune) error {
+ r, size, err := state.ReadRune()
+ rs.rune = r
+ rs.size = size
+ return err
+}
+
+func TestScanStateCount(t *testing.T) {
+ var a, b, c runeScanner
+ n, err := Sscanf("12➂", "%c%c%c", &a, &b, &c)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if n != 3 {
+ t.Fatalf("expected 3 items consumed, got %d")
+ }
+ if a.rune != '1' || b.rune != '2' || c.rune != '➂' {
+ t.Errorf("bad scan rune: %q %q %q should be '1' '2' '➂'", a.rune, b.rune, c.rune)
+ }
+ if a.size != 1 || b.size != 1 || c.size != 3 {
+ t.Errorf("bad scan size: %q %q %q should be 1 1 3", a.size, b.size, c.size)
+ }
+}
+
// RecursiveInt accepts a string matching %d.%d.%d....
// and parses it into a linked list.
// It allows us to benchmark recursive descent style scanners.