aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/fmt/print.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/fmt/print.go')
-rw-r--r--libgo/go/fmt/print.go232
1 files changed, 123 insertions, 109 deletions
diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go
index 42fcd8b..5958691 100644
--- a/libgo/go/fmt/print.go
+++ b/libgo/go/fmt/print.go
@@ -5,7 +5,6 @@
package fmt
import (
- "errors"
"internal/fmtsort"
"io"
"os"
@@ -75,19 +74,19 @@ type GoStringer interface {
// Use simple []byte instead of bytes.Buffer to avoid large dependency.
type buffer []byte
-func (b *buffer) Write(p []byte) {
+func (b *buffer) write(p []byte) {
*b = append(*b, p...)
}
-func (b *buffer) WriteString(s string) {
+func (b *buffer) writeString(s string) {
*b = append(*b, s...)
}
-func (b *buffer) WriteByte(c byte) {
+func (b *buffer) writeByte(c byte) {
*b = append(*b, c)
}
-func (bp *buffer) WriteRune(r rune) {
+func (bp *buffer) writeRune(r rune) {
if r < utf8.RuneSelf {
*bp = append(*bp, byte(r))
return
@@ -123,6 +122,10 @@ type pp struct {
panicking bool
// erroring is set when printing an error string to guard against calling handleMethods.
erroring bool
+ // wrapErrs is set when the format string may contain a %w verb.
+ wrapErrs bool
+ // wrappedErr records the target of the %w verb.
+ wrappedErr error
}
var ppFree = sync.Pool{
@@ -134,6 +137,7 @@ func newPrinter() *pp {
p := ppFree.Get().(*pp)
p.panicking = false
p.erroring = false
+ p.wrapErrs = false
p.fmt.init(&p.buf)
return p
}
@@ -153,6 +157,7 @@ func (p *pp) free() {
p.buf = p.buf[:0]
p.arg = nil
p.value = reflect.Value{}
+ p.wrappedErr = nil
ppFree.Put(p)
}
@@ -179,14 +184,14 @@ func (p *pp) Flag(b int) bool {
// Implement Write so we can call Fprintf on a pp (through State), for
// recursive use in custom verbs.
func (p *pp) Write(b []byte) (ret int, err error) {
- p.buf.Write(b)
+ p.buf.write(b)
return len(b), nil
}
// Implement WriteString so that we can call io.WriteString
// on a pp (through state), for efficiency.
func (p *pp) WriteString(s string) (ret int, err error) {
- p.buf.WriteString(s)
+ p.buf.writeString(s)
return len(s), nil
}
@@ -217,12 +222,6 @@ func Sprintf(format string, a ...interface{}) string {
return s
}
-// Errorf formats according to a format specifier and returns the string
-// as a value that satisfies error.
-func Errorf(format string, a ...interface{}) error {
- return errors.New(Sprintf(format, a...))
-}
-
// These routines do not take a format string
// Fprint formats using the default formats for its operands and writes to w.
@@ -320,32 +319,32 @@ func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
func (p *pp) unknownType(v reflect.Value) {
if !v.IsValid() {
- p.buf.WriteString(nilAngleString)
+ p.buf.writeString(nilAngleString)
return
}
- p.buf.WriteByte('?')
- p.buf.WriteString(v.Type().String())
- p.buf.WriteByte('?')
+ p.buf.writeByte('?')
+ p.buf.writeString(v.Type().String())
+ p.buf.writeByte('?')
}
func (p *pp) badVerb(verb rune) {
p.erroring = true
- p.buf.WriteString(percentBangString)
- p.buf.WriteRune(verb)
- p.buf.WriteByte('(')
+ p.buf.writeString(percentBangString)
+ p.buf.writeRune(verb)
+ p.buf.writeByte('(')
switch {
case p.arg != nil:
- p.buf.WriteString(reflect.TypeOf(p.arg).String())
- p.buf.WriteByte('=')
+ p.buf.writeString(reflect.TypeOf(p.arg).String())
+ p.buf.writeByte('=')
p.printArg(p.arg, 'v')
case p.value.IsValid():
- p.buf.WriteString(p.value.Type().String())
- p.buf.WriteByte('=')
+ p.buf.writeString(p.value.Type().String())
+ p.buf.writeByte('=')
p.printValue(p.value, 'v', 0)
default:
- p.buf.WriteString(nilAngleString)
+ p.buf.writeString(nilAngleString)
}
- p.buf.WriteByte(')')
+ p.buf.writeByte(')')
p.erroring = false
}
@@ -363,7 +362,7 @@ func (p *pp) fmtBool(v bool, verb rune) {
func (p *pp) fmt0x64(v uint64, leading0x bool) {
sharp := p.fmt.sharp
p.fmt.sharp = leading0x
- p.fmt.fmtInteger(v, 16, unsigned, ldigits)
+ p.fmt.fmtInteger(v, 16, unsigned, 'v', ldigits)
p.fmt.sharp = sharp
}
@@ -374,18 +373,18 @@ func (p *pp) fmtInteger(v uint64, isSigned bool, verb rune) {
if p.fmt.sharpV && !isSigned {
p.fmt0x64(v, true)
} else {
- p.fmt.fmtInteger(v, 10, isSigned, ldigits)
+ p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits)
}
case 'd':
- p.fmt.fmtInteger(v, 10, isSigned, ldigits)
+ p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits)
case 'b':
- p.fmt.fmtInteger(v, 2, isSigned, ldigits)
- case 'o':
- p.fmt.fmtInteger(v, 8, isSigned, ldigits)
+ p.fmt.fmtInteger(v, 2, isSigned, verb, ldigits)
+ case 'o', 'O':
+ p.fmt.fmtInteger(v, 8, isSigned, verb, ldigits)
case 'x':
- p.fmt.fmtInteger(v, 16, isSigned, ldigits)
+ p.fmt.fmtInteger(v, 16, isSigned, verb, ldigits)
case 'X':
- p.fmt.fmtInteger(v, 16, isSigned, udigits)
+ p.fmt.fmtInteger(v, 16, isSigned, verb, udigits)
case 'c':
p.fmt.fmtC(v)
case 'q':
@@ -407,7 +406,7 @@ func (p *pp) fmtFloat(v float64, size int, verb rune) {
switch verb {
case 'v':
p.fmt.fmtFloat(v, size, 'g', -1)
- case 'b', 'g', 'G':
+ case 'b', 'g', 'G', 'x', 'X':
p.fmt.fmtFloat(v, size, verb, -1)
case 'f', 'e', 'E':
p.fmt.fmtFloat(v, size, verb, 6)
@@ -425,14 +424,14 @@ func (p *pp) fmtComplex(v complex128, size int, verb rune) {
// Make sure any unsupported verbs are found before the
// calls to fmtFloat to not generate an incorrect error string.
switch verb {
- case 'v', 'b', 'g', 'G', 'f', 'F', 'e', 'E':
+ case 'v', 'b', 'g', 'G', 'x', 'X', 'f', 'F', 'e', 'E':
oldPlus := p.fmt.plus
- p.buf.WriteByte('(')
+ p.buf.writeByte('(')
p.fmtFloat(real(v), size/2, verb)
// Imaginary part always has a sign.
p.fmt.plus = true
p.fmtFloat(imag(v), size/2, verb)
- p.buf.WriteString("i)")
+ p.buf.writeString("i)")
p.fmt.plus = oldPlus
default:
p.badVerb(verb)
@@ -464,28 +463,28 @@ func (p *pp) fmtBytes(v []byte, verb rune, typeString string) {
switch verb {
case 'v', 'd':
if p.fmt.sharpV {
- p.buf.WriteString(typeString)
+ p.buf.writeString(typeString)
if v == nil {
- p.buf.WriteString(nilParenString)
+ p.buf.writeString(nilParenString)
return
}
- p.buf.WriteByte('{')
+ p.buf.writeByte('{')
for i, c := range v {
if i > 0 {
- p.buf.WriteString(commaSpaceString)
+ p.buf.writeString(commaSpaceString)
}
p.fmt0x64(uint64(c), true)
}
- p.buf.WriteByte('}')
+ p.buf.writeByte('}')
} else {
- p.buf.WriteByte('[')
+ p.buf.writeByte('[')
for i, c := range v {
if i > 0 {
- p.buf.WriteByte(' ')
+ p.buf.writeByte(' ')
}
- p.fmt.fmtInteger(uint64(c), 10, unsigned, ldigits)
+ p.fmt.fmtInteger(uint64(c), 10, unsigned, verb, ldigits)
}
- p.buf.WriteByte(']')
+ p.buf.writeByte(']')
}
case 's':
p.fmt.fmtBs(v)
@@ -513,15 +512,15 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune) {
switch verb {
case 'v':
if p.fmt.sharpV {
- p.buf.WriteByte('(')
- p.buf.WriteString(value.Type().String())
- p.buf.WriteString(")(")
+ p.buf.writeByte('(')
+ p.buf.writeString(value.Type().String())
+ p.buf.writeString(")(")
if u == 0 {
- p.buf.WriteString(nilString)
+ p.buf.writeString(nilString)
} else {
p.fmt0x64(uint64(u), true)
}
- p.buf.WriteByte(')')
+ p.buf.writeByte(')')
} else {
if u == 0 {
p.fmt.padString(nilAngleString)
@@ -544,7 +543,7 @@ func (p *pp) catchPanic(arg interface{}, verb rune, method string) {
// Stringer that fails to guard against nil or a nil pointer for a
// value receiver, and in either case, "<nil>" is a nice result.
if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() {
- p.buf.WriteString(nilAngleString)
+ p.buf.writeString(nilAngleString)
return
}
// Otherwise print a concise panic message. Most of the time the panic
@@ -558,15 +557,15 @@ func (p *pp) catchPanic(arg interface{}, verb rune, method string) {
// For this output we want default behavior.
p.fmt.clearflags()
- p.buf.WriteString(percentBangString)
- p.buf.WriteRune(verb)
- p.buf.WriteString(panicString)
- p.buf.WriteString(method)
- p.buf.WriteString(" method: ")
+ p.buf.writeString(percentBangString)
+ p.buf.writeRune(verb)
+ p.buf.writeString(panicString)
+ p.buf.writeString(method)
+ p.buf.writeString(" method: ")
p.panicking = true
p.printArg(err, 'v')
p.panicking = false
- p.buf.WriteByte(')')
+ p.buf.writeByte(')')
p.fmt.fmtFlags = oldFlags
}
@@ -576,6 +575,21 @@ func (p *pp) handleMethods(verb rune) (handled bool) {
if p.erroring {
return
}
+ if verb == 'w' {
+ // It is invalid to use %w other than with Errorf, more than once,
+ // or with a non-error arg.
+ err, ok := p.arg.(error)
+ if !ok || !p.wrapErrs || p.wrappedErr != nil {
+ p.wrappedErr = nil
+ p.wrapErrs = false
+ p.badVerb(verb)
+ return true
+ }
+ p.wrappedErr = err
+ // If the arg is a Formatter, pass 'v' as the verb to it.
+ verb = 'v'
+ }
+
// Is it a Formatter?
if formatter, ok := p.arg.(Formatter); ok {
handled = true
@@ -720,11 +734,11 @@ func (p *pp) printValue(value reflect.Value, verb rune, depth int) {
switch f := value; value.Kind() {
case reflect.Invalid:
if depth == 0 {
- p.buf.WriteString(invReflectString)
+ p.buf.writeString(invReflectString)
} else {
switch verb {
case 'v':
- p.buf.WriteString(nilAngleString)
+ p.buf.writeString(nilAngleString)
default:
p.badVerb(verb)
}
@@ -747,63 +761,63 @@ func (p *pp) printValue(value reflect.Value, verb rune, depth int) {
p.fmtString(f.String(), verb)
case reflect.Map:
if p.fmt.sharpV {
- p.buf.WriteString(f.Type().String())
+ p.buf.writeString(f.Type().String())
if f.IsNil() {
- p.buf.WriteString(nilParenString)
+ p.buf.writeString(nilParenString)
return
}
- p.buf.WriteByte('{')
+ p.buf.writeByte('{')
} else {
- p.buf.WriteString(mapString)
+ p.buf.writeString(mapString)
}
sorted := fmtsort.Sort(f)
for i, key := range sorted.Key {
if i > 0 {
if p.fmt.sharpV {
- p.buf.WriteString(commaSpaceString)
+ p.buf.writeString(commaSpaceString)
} else {
- p.buf.WriteByte(' ')
+ p.buf.writeByte(' ')
}
}
p.printValue(key, verb, depth+1)
- p.buf.WriteByte(':')
+ p.buf.writeByte(':')
p.printValue(sorted.Value[i], verb, depth+1)
}
if p.fmt.sharpV {
- p.buf.WriteByte('}')
+ p.buf.writeByte('}')
} else {
- p.buf.WriteByte(']')
+ p.buf.writeByte(']')
}
case reflect.Struct:
if p.fmt.sharpV {
- p.buf.WriteString(f.Type().String())
+ p.buf.writeString(f.Type().String())
}
- p.buf.WriteByte('{')
+ p.buf.writeByte('{')
for i := 0; i < f.NumField(); i++ {
if i > 0 {
if p.fmt.sharpV {
- p.buf.WriteString(commaSpaceString)
+ p.buf.writeString(commaSpaceString)
} else {
- p.buf.WriteByte(' ')
+ p.buf.writeByte(' ')
}
}
if p.fmt.plusV || p.fmt.sharpV {
if name := f.Type().Field(i).Name; name != "" {
- p.buf.WriteString(name)
- p.buf.WriteByte(':')
+ p.buf.writeString(name)
+ p.buf.writeByte(':')
}
}
p.printValue(getField(f, i), verb, depth+1)
}
- p.buf.WriteByte('}')
+ p.buf.writeByte('}')
case reflect.Interface:
value := f.Elem()
if !value.IsValid() {
if p.fmt.sharpV {
- p.buf.WriteString(f.Type().String())
- p.buf.WriteString(nilParenString)
+ p.buf.writeString(f.Type().String())
+ p.buf.writeString(nilParenString)
} else {
- p.buf.WriteString(nilAngleString)
+ p.buf.writeString(nilAngleString)
}
} else {
p.printValue(value, verb, depth+1)
@@ -833,28 +847,28 @@ func (p *pp) printValue(value reflect.Value, verb rune, depth int) {
}
}
if p.fmt.sharpV {
- p.buf.WriteString(f.Type().String())
+ p.buf.writeString(f.Type().String())
if f.Kind() == reflect.Slice && f.IsNil() {
- p.buf.WriteString(nilParenString)
+ p.buf.writeString(nilParenString)
return
}
- p.buf.WriteByte('{')
+ p.buf.writeByte('{')
for i := 0; i < f.Len(); i++ {
if i > 0 {
- p.buf.WriteString(commaSpaceString)
+ p.buf.writeString(commaSpaceString)
}
p.printValue(f.Index(i), verb, depth+1)
}
- p.buf.WriteByte('}')
+ p.buf.writeByte('}')
} else {
- p.buf.WriteByte('[')
+ p.buf.writeByte('[')
for i := 0; i < f.Len(); i++ {
if i > 0 {
- p.buf.WriteByte(' ')
+ p.buf.writeByte(' ')
}
p.printValue(f.Index(i), verb, depth+1)
}
- p.buf.WriteByte(']')
+ p.buf.writeByte(']')
}
case reflect.Ptr:
// pointer to array or slice or struct? ok at top level
@@ -862,7 +876,7 @@ func (p *pp) printValue(value reflect.Value, verb rune, depth int) {
if depth == 0 && f.Pointer() != 0 {
switch a := f.Elem(); a.Kind() {
case reflect.Array, reflect.Slice, reflect.Struct, reflect.Map:
- p.buf.WriteByte('&')
+ p.buf.writeByte('&')
p.printValue(a, verb, depth+1)
return
}
@@ -950,15 +964,15 @@ func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum
}
func (p *pp) badArgNum(verb rune) {
- p.buf.WriteString(percentBangString)
- p.buf.WriteRune(verb)
- p.buf.WriteString(badIndexString)
+ p.buf.writeString(percentBangString)
+ p.buf.writeRune(verb)
+ p.buf.writeString(badIndexString)
}
func (p *pp) missingArg(verb rune) {
- p.buf.WriteString(percentBangString)
- p.buf.WriteRune(verb)
- p.buf.WriteString(missingString)
+ p.buf.writeString(percentBangString)
+ p.buf.writeRune(verb)
+ p.buf.writeString(missingString)
}
func (p *pp) doPrintf(format string, a []interface{}) {
@@ -974,7 +988,7 @@ formatLoop:
i++
}
if i > lasti {
- p.buf.WriteString(format[lasti:i])
+ p.buf.writeString(format[lasti:i])
}
if i >= end {
// done processing format string
@@ -1032,7 +1046,7 @@ formatLoop:
p.fmt.wid, p.fmt.widPresent, argNum = intFromArg(a, argNum)
if !p.fmt.widPresent {
- p.buf.WriteString(badWidthString)
+ p.buf.writeString(badWidthString)
}
// We have a negative width, so take its value and ensure
@@ -1066,7 +1080,7 @@ formatLoop:
p.fmt.precPresent = false
}
if !p.fmt.precPresent {
- p.buf.WriteString(badPrecString)
+ p.buf.writeString(badPrecString)
}
afterIndex = false
} else {
@@ -1083,7 +1097,7 @@ formatLoop:
}
if i >= end {
- p.buf.WriteString(noVerbString)
+ p.buf.writeString(noVerbString)
break
}
@@ -1095,7 +1109,7 @@ formatLoop:
switch {
case verb == '%': // Percent does not absorb operands and ignores f.wid and f.prec.
- p.buf.WriteByte('%')
+ p.buf.writeByte('%')
case !p.goodArgNum:
p.badArgNum(verb)
case argNum >= len(a): // No argument left over to print for the current verb.
@@ -1119,20 +1133,20 @@ formatLoop:
// been used and arguably OK if they're not.
if !p.reordered && argNum < len(a) {
p.fmt.clearflags()
- p.buf.WriteString(extraString)
+ p.buf.writeString(extraString)
for i, arg := range a[argNum:] {
if i > 0 {
- p.buf.WriteString(commaSpaceString)
+ p.buf.writeString(commaSpaceString)
}
if arg == nil {
- p.buf.WriteString(nilAngleString)
+ p.buf.writeString(nilAngleString)
} else {
- p.buf.WriteString(reflect.TypeOf(arg).String())
- p.buf.WriteByte('=')
+ p.buf.writeString(reflect.TypeOf(arg).String())
+ p.buf.writeByte('=')
p.printArg(arg, 'v')
}
}
- p.buf.WriteByte(')')
+ p.buf.writeByte(')')
}
}
@@ -1142,7 +1156,7 @@ func (p *pp) doPrint(a []interface{}) {
isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
// Add a space between two non-string arguments.
if argNum > 0 && !isString && !prevString {
- p.buf.WriteByte(' ')
+ p.buf.writeByte(' ')
}
p.printArg(arg, 'v')
prevString = isString
@@ -1154,9 +1168,9 @@ func (p *pp) doPrint(a []interface{}) {
func (p *pp) doPrintln(a []interface{}) {
for argNum, arg := range a {
if argNum > 0 {
- p.buf.WriteByte(' ')
+ p.buf.writeByte(' ')
}
p.printArg(arg, 'v')
}
- p.buf.WriteByte('\n')
+ p.buf.writeByte('\n')
}