diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-11-06 19:49:01 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-11-06 19:49:01 +0000 |
commit | f038dae646bac2b31be98ab592c0e5206d2d96f5 (patch) | |
tree | 39530b071991b2326f881b2a30a2d82d6c133fd6 /libgo/go/fmt | |
parent | f20f261304993444741e0f0a14d3147e591bc660 (diff) | |
download | gcc-f038dae646bac2b31be98ab592c0e5206d2d96f5.zip gcc-f038dae646bac2b31be98ab592c0e5206d2d96f5.tar.gz gcc-f038dae646bac2b31be98ab592c0e5206d2d96f5.tar.bz2 |
libgo: Update to October 24 version of master library.
From-SVN: r204466
Diffstat (limited to 'libgo/go/fmt')
-rw-r--r-- | libgo/go/fmt/doc.go | 33 | ||||
-rw-r--r-- | libgo/go/fmt/fmt_test.go | 89 | ||||
-rw-r--r-- | libgo/go/fmt/format.go | 23 | ||||
-rw-r--r-- | libgo/go/fmt/print.go | 282 | ||||
-rw-r--r-- | libgo/go/fmt/scan.go | 67 | ||||
-rw-r--r-- | libgo/go/fmt/scan_test.go | 5 |
6 files changed, 342 insertions, 157 deletions
diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go index b8dd995..095fd03 100644 --- a/libgo/go/fmt/doc.go +++ b/libgo/go/fmt/doc.go @@ -118,6 +118,28 @@ convert the value before recurring: func (x X) String() string { return Sprintf("<%s>", string(x)) } + Explicit argument indexes: + + In Printf, Sprintf, and Fprintf, the default behavior is for each + formatting verb to format successive arguments passed in the call. + However, the notation [n] immediately before the verb indicates that the + nth one-indexed argument is to be formatted instead. The same notation + before a '*' for a width or precision selects the argument index holding + the value. After processing a bracketed expression [n], arguments n+1, + n+2, etc. will be processed unless otherwise directed. + + For example, + fmt.Sprintf("%[2]d %[1]d\n", 11, 22) + will yield "22, 11", while + fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6), + equivalent to + fmt.Sprintf("%6.2f", 12.0), + will yield " 12.00". Because an explicit index affects subsequent verbs, + this notation can be used to print the same values multiple times + by resetting the index for the first argument to be repeated: + fmt.Sprintf("%d %d %#[1]x %#x", 16, 17) + will yield "16 17 0x10 0x11". + Format errors: If an invalid argument is given for a verb, such as providing @@ -133,6 +155,9 @@ Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC) Printf("%*s", 4.5, "hi"): %!(BADWIDTH)hi Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi + Invalid or invalid use of argument index: %!(BADINDEX) + Printf("%*[2]d", 7): %!d(BADINDEX) + Printf("%.[2]d", 7): %!d(BADINDEX) All errors begin with the string "%!" followed sometimes by a single character (the verb) and end with a parenthesized @@ -144,9 +169,9 @@ through the fmt package. For example, if a String method calls panic("bad"), the resulting formatted message will look like - %s(PANIC=bad) + %!s(PANIC=bad) - The %s just shows the print verb in use when the failure + The %!s just shows the print verb in use when the failure occurred. Scanning @@ -190,6 +215,10 @@ stops if it does not, with the return value of the function indicating the number of arguments scanned. + In all the scanning functions, a carriage return followed + immediately by a newline is treated as a plain newline + (\r\n means the same as \n). + In all the scanning functions, if an operand implements method Scan (that is, it implements the Scanner interface) that method will be used to scan the text for that operand. Also, diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go index df9e5a0..bbca2c5 100644 --- a/libgo/go/fmt/fmt_test.go +++ b/libgo/go/fmt/fmt_test.go @@ -110,7 +110,7 @@ var bslice = barray[:] var b byte -var fmttests = []struct { +var fmtTests = []struct { fmt string val interface{} out string @@ -227,6 +227,8 @@ var fmttests = []struct { {"%+.3g", -1.0, "-1"}, {"% .3g", -1.0, "-1"}, {"% .3g", 1.0, " 1"}, + {"%b", float32(1.0), "8388608p-23"}, + {"%b", 1.0, "4503599627370496p-52"}, // complex values {"%+.3e", 0i, "(+0.000e+00+0.000e+00i)"}, @@ -247,6 +249,8 @@ var fmttests = []struct { {"% .3E", -1 - 2i, "(-1.000E+00-2.000E+00i)"}, {"%+.3g", complex64(1 + 2i), "(+1+2i)"}, {"%+.3g", complex128(1 + 2i), "(+1+2i)"}, + {"%b", complex64(1 + 2i), "(8388608p-23+8388608p-22i)"}, + {"%b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"}, // erroneous formats {"", 2, "%!(EXTRA int=2)"}, @@ -493,6 +497,17 @@ var fmttests = []struct { // Used to crash because nByte didn't allow for a sign. {"%b", int64(-1 << 63), "-1000000000000000000000000000000000000000000000000000000000000000"}, + // Used to panic. + {"%0100d", 1, "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"}, + {"%0100d", -1, "-000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"}, + {"%0.100f", 1.0, "1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, + {"%0.100f", -1.0, "-1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, + + // Zero padding floats used to put the minus sign in the middle. + {"%020f", -1.0, "-000000000001.000000"}, + {"%20f", -1.0, " -1.000000"}, + {"%0100f", -1.0, "-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.000000"}, + // Complex fmt used to leave the plus flag set for future entries in the array // causing +2+0i and +3+0i instead of 2+0i and 3+0i. {"%v", []complex64{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"}, @@ -503,7 +518,7 @@ var fmttests = []struct { } func TestSprintf(t *testing.T) { - for _, tt := range fmttests { + for _, tt := range fmtTests { s := Sprintf(tt.fmt, tt.val) if i := strings.Index(tt.out, "PTR"); i >= 0 { pattern := "PTR" @@ -539,6 +554,55 @@ func TestSprintf(t *testing.T) { } } +type SE []interface{} // slice of empty; notational compactness. + +var reorderTests = []struct { + fmt string + val SE + out string +}{ + {"%[1]d", SE{1}, "1"}, + {"%[2]d", SE{2, 1}, "1"}, + {"%[2]d %[1]d", SE{1, 2}, "2 1"}, + {"%[2]*[1]d", SE{2, 5}, " 2"}, + {"%6.2f", SE{12.0}, " 12.00"}, // Explicit version of next line. + {"%[3]*.[2]*[1]f", SE{12.0, 2, 6}, " 12.00"}, + {"%[1]*.[2]*[3]f", SE{6, 2, 12.0}, " 12.00"}, + {"%10f", SE{12.0}, " 12.000000"}, + {"%[1]*[3]f", SE{10, 99, 12.0}, " 12.000000"}, + {"%.6f", SE{12.0}, "12.000000"}, // Explicit version of next line. + {"%.[1]*[3]f", SE{6, 99, 12.0}, "12.000000"}, + {"%6.f", SE{12.0}, " 12"}, // // Explicit version of next line; empty precision means zero. + {"%[1]*.[3]f", SE{6, 3, 12.0}, " 12"}, + // An actual use! Print the same arguments twice. + {"%d %d %d %#[1]o %#o %#o", SE{11, 12, 13}, "11 12 13 013 014 015"}, + + // Erroneous cases. + {"%[d", SE{2, 1}, "%!d(BADINDEX)"}, + {"%]d", SE{2, 1}, "%!](int=2)d%!(EXTRA int=1)"}, + {"%[]d", SE{2, 1}, "%!d(BADINDEX)"}, + {"%[-3]d", SE{2, 1}, "%!d(BADINDEX)"}, + {"%[99]d", SE{2, 1}, "%!d(BADINDEX)"}, + {"%[3]", SE{2, 1}, "%!(NOVERB)"}, + {"%[1].2d", SE{5, 6}, "%!d(BADINDEX)"}, + {"%[1]2d", SE{2, 1}, "%!d(BADINDEX)"}, + {"%3.[2]d", SE{7}, "%!d(BADINDEX)"}, + {"%.[2]d", SE{7}, "%!d(BADINDEX)"}, + {"%d %d %d %#[1]o %#o %#o %#o", SE{11, 12, 13}, "11 12 13 013 014 015 %!o(MISSING)"}, + {"%[5]d %[2]d %d", SE{1, 2, 3}, "%!d(BADINDEX) 2 3"}, + {"%d %[3]d %d", SE{1, 2}, "1 %!d(BADINDEX) 2"}, // Erroneous index does not affect sequence. +} + +func TestReorder(t *testing.T) { + for _, tt := range reorderTests { + s := Sprintf(tt.fmt, tt.val...) + if s != tt.out { + t.Errorf("Sprintf(%q, %v) = <%s> want <%s>", tt.fmt, tt.val, s, tt.out) + } else { + } + } +} + func BenchmarkSprintfEmpty(b *testing.B) { for i := 0; i < b.N; i++ { Sprintf("") @@ -607,6 +671,9 @@ var mallocTest = []struct { var _ bytes.Buffer func TestCountMallocs(t *testing.T) { + if testing.Short() { + t.Skip("skipping malloc count in short mode") + } if runtime.GOMAXPROCS(0) > 1 { t.Skip("skipping; GOMAXPROCS>1") } @@ -832,16 +899,16 @@ var panictests = []struct { }{ // String {"%s", (*Panic)(nil), "<nil>"}, // nil pointer special case - {"%s", Panic{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"}, - {"%s", Panic{3}, "%s(PANIC=3)"}, + {"%s", Panic{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"}, + {"%s", Panic{3}, "%!s(PANIC=3)"}, // GoString {"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case - {"%#v", Panic{io.ErrUnexpectedEOF}, "%v(PANIC=unexpected EOF)"}, - {"%#v", Panic{3}, "%v(PANIC=3)"}, + {"%#v", Panic{io.ErrUnexpectedEOF}, "%!v(PANIC=unexpected EOF)"}, + {"%#v", Panic{3}, "%!v(PANIC=3)"}, // Format {"%s", (*PanicF)(nil), "<nil>"}, // nil pointer special case - {"%s", PanicF{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"}, - {"%s", PanicF{3}, "%s(PANIC=3)"}, + {"%s", PanicF{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"}, + {"%s", PanicF{3}, "%!s(PANIC=3)"}, } func TestPanics(t *testing.T) { @@ -861,7 +928,7 @@ type Recur struct { failed *bool } -func (r Recur) String() string { +func (r *Recur) String() string { if recurCount++; recurCount > 10 { *r.failed = true return "FAIL" @@ -874,13 +941,13 @@ func (r Recur) String() string { func TestBadVerbRecursion(t *testing.T) { failed := false - r := Recur{3, &failed} + r := &Recur{3, &failed} Sprintf("recur@%p value: %d\n", &r, r.i) if failed { t.Error("fail with pointer") } failed = false - r = Recur{4, &failed} + r = &Recur{4, &failed} Sprintf("recur@%p, value: %d\n", r, r.i) if failed { t.Error("fail with value") diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go index 5665db1..2e2b071 100644 --- a/libgo/go/fmt/format.go +++ b/libgo/go/fmt/format.go @@ -24,8 +24,6 @@ const ( var padZeroBytes = make([]byte, nByte) var padSpaceBytes = make([]byte, nByte) -var newline = []byte{'\n'} - func init() { for i := 0; i < nByte; i++ { padZeroBytes[i] = '0' @@ -162,6 +160,11 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { } var buf []byte = f.intbuf[0:] + if f.widPresent && f.wid > nByte { + // We're going to need a bigger boat. + buf = make([]byte, f.wid) + } + negative := signedness == signed && a < 0 if negative { a = -a @@ -184,7 +187,7 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { // a is made into unsigned ua. we could make things // marginally faster by splitting the 32-bit case out into a separate // block but it's not worth the duplication, so ua has 64 bits. - i := len(f.intbuf) + i := len(buf) ua := uint64(a) for ua >= base { i-- @@ -193,7 +196,7 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { } i-- buf[i] = digits[ua] - for i > 0 && prec > nByte-i { + for i > 0 && prec > len(buf)-i { i-- buf[i] = '0' } @@ -356,6 +359,14 @@ func (f *fmt) formatFloat(v float64, verb byte, prec, n int) { // The formatted number starts at slice[1]. switch slice[1] { case '-', '+': + // If we're zero padding, want the sign before the leading zeros. + // Achieve this by writing the sign out and padding the postive number. + if f.zero && f.widPresent && f.wid > len(slice) { + f.buf.WriteByte(slice[1]) + f.wid-- + f.pad(slice[2:]) + return + } // We're set; drop the leading space. slice = slice[1:] default: @@ -418,6 +429,8 @@ func (f *fmt) fmt_c64(v complex64, verb rune) { oldPlus := f.plus for i := 0; ; i++ { switch verb { + case 'b': + f.fmt_fb32(r) case 'e': f.fmt_e32(r) case 'E': @@ -446,6 +459,8 @@ func (f *fmt) fmt_c128(v complex128, verb rune) { oldPlus := f.plus for i := 0; ; i++ { switch verb { + case 'b': + f.fmt_fb64(r) case 'e': f.fmt_e64(r) case 'E': diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go index 5f37fd1..1ea816d 100644 --- a/libgo/go/fmt/print.go +++ b/libgo/go/fmt/print.go @@ -16,19 +16,21 @@ import ( // Some constants in the form of bytes, to avoid string overhead. // Needlessly fastidious, I suppose. var ( - commaSpaceBytes = []byte(", ") - nilAngleBytes = []byte("<nil>") - nilParenBytes = []byte("(nil)") - nilBytes = []byte("nil") - mapBytes = []byte("map[") - missingBytes = []byte("(MISSING)") - panicBytes = []byte("(PANIC=") - extraBytes = []byte("%!(EXTRA ") - irparenBytes = []byte("i)") - bytesBytes = []byte("[]byte{") - badWidthBytes = []byte("%!(BADWIDTH)") - badPrecBytes = []byte("%!(BADPREC)") - noVerbBytes = []byte("%!(NOVERB)") + commaSpaceBytes = []byte(", ") + nilAngleBytes = []byte("<nil>") + nilParenBytes = []byte("(nil)") + nilBytes = []byte("nil") + mapBytes = []byte("map[") + percentBangBytes = []byte("%!") + missingBytes = []byte("(MISSING)") + badIndexBytes = []byte("(BADINDEX)") + panicBytes = []byte("(PANIC=") + extraBytes = []byte("%!(EXTRA ") + irparenBytes = []byte("i)") + bytesBytes = []byte("[]byte{") + badWidthBytes = []byte("%!(BADWIDTH)") + badPrecBytes = []byte("%!(BADPREC)") + noVerbBytes = []byte("%!(NOVERB)") ) // State represents the printer state passed to custom formatters. @@ -42,7 +44,7 @@ type State interface { // Precision returns the value of the precision option and whether it has been set. Precision() (prec int, ok bool) - // Flag returns whether the flag c, a character, has been set. + // Flag reports whether the flag c, a character, has been set. Flag(c int) bool } @@ -109,13 +111,17 @@ type pp struct { panicking bool erroring bool // printing an error condition buf buffer - // field holds the current item, as an interface{}. - field interface{} + // arg holds the current item, as an interface{}. + arg interface{} // value holds the current item, as a reflect.Value, and will be // the zero Value if the item has not been reflected. - value reflect.Value - runeBuf [utf8.UTFMax]byte - fmt fmt + value reflect.Value + // reordered records whether the format string used argument reordering. + reordered bool + // goodArgNum records whether the most recent reordering directive was valid. + goodArgNum bool + runeBuf [utf8.UTFMax]byte + fmt fmt } // A cache holds a set of reusable objects. @@ -170,7 +176,7 @@ func (p *pp) free() { return } p.buf = p.buf[:0] - p.field = nil + p.arg = nil p.value = reflect.Value{} ppFree.put(p) } @@ -212,9 +218,9 @@ func (p *pp) Write(b []byte) (ret int, err error) { func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { p := newPrinter() p.doPrintf(format, a) - n64, err := w.Write(p.buf) + n, err = w.Write(p.buf) p.free() - return int(n64), err + return } // Printf formats according to a format specifier and writes to standard output. @@ -246,9 +252,9 @@ func Errorf(format string, a ...interface{}) error { func Fprint(w io.Writer, a ...interface{}) (n int, err error) { p := newPrinter() p.doPrint(a, false, false) - n64, err := w.Write(p.buf) + n, err = w.Write(p.buf) p.free() - return int(n64), err + return } // Print formats using the default formats for its operands and writes to standard output. @@ -278,9 +284,9 @@ func Sprint(a ...interface{}) string { func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { p := newPrinter() p.doPrint(a, true, true) - n64, err := w.Write(p.buf) + n, err = w.Write(p.buf) p.free() - return int(n64), err + return } // Println formats using the default formats for its operands and writes to standard output. @@ -300,8 +306,8 @@ func Sprintln(a ...interface{}) string { return s } -// getField gets the i'th arg of the struct value. -// If the arg itself is an interface, return a value for +// getField gets the i'th field of the struct value. +// If the field is itself is an interface, return a value for // the thing inside the interface, not the interface itself. func getField(v reflect.Value, i int) reflect.Value { val := v.Field(i) @@ -340,10 +346,10 @@ func (p *pp) badVerb(verb rune) { p.add(verb) p.add('(') switch { - case p.field != nil: - p.buf.WriteString(reflect.TypeOf(p.field).String()) + case p.arg != nil: + p.buf.WriteString(reflect.TypeOf(p.arg).String()) p.add('=') - p.printField(p.field, 'v', false, false, 0) + p.printArg(p.arg, 'v', false, false, 0) case p.value.IsValid(): p.buf.WriteString(p.value.Type().String()) p.add('=') @@ -505,7 +511,7 @@ func (p *pp) fmtFloat64(v float64, verb rune) { func (p *pp) fmtComplex64(v complex64, verb rune) { switch verb { - case 'e', 'E', 'f', 'F', 'g', 'G': + case 'b', 'e', 'E', 'f', 'F', 'g', 'G': p.fmt.fmt_c64(v, verb) case 'v': p.fmt.fmt_c64(v, 'g') @@ -516,7 +522,7 @@ func (p *pp) fmtComplex64(v complex64, verb rune) { func (p *pp) fmtComplex128(v complex128, verb rune) { switch verb { - case 'e', 'E', 'f', 'F', 'g', 'G': + case 'b', 'e', 'E', 'f', 'F', 'g', 'G': p.fmt.fmt_c128(v, verb) case 'v': p.fmt.fmt_c128(v, 'g') @@ -566,7 +572,7 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, dept p.buf.WriteByte(' ') } } - p.printField(c, 'v', p.fmt.plus, goSyntax, depth+1) + p.printArg(c, 'v', p.fmt.plus, goSyntax, depth+1) } if goSyntax { p.buf.WriteByte('}') @@ -635,31 +641,29 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) { var ( intBits = reflect.TypeOf(0).Bits() - floatBits = reflect.TypeOf(0.0).Bits() - complexBits = reflect.TypeOf(1i).Bits() uintptrBits = reflect.TypeOf(uintptr(0)).Bits() ) -func (p *pp) catchPanic(field interface{}, verb rune) { +func (p *pp) catchPanic(arg interface{}, verb rune) { if err := recover(); err != nil { // If it's a nil pointer, just say "<nil>". The likeliest causes are a // 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(field); v.Kind() == reflect.Ptr && v.IsNil() { + if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() { p.buf.Write(nilAngleBytes) return } // Otherwise print a concise panic message. Most of the time the panic // value will print itself nicely. if p.panicking { - // Nested panics; the recursion in printField cannot succeed. + // Nested panics; the recursion in printArg cannot succeed. panic(err) } - p.buf.WriteByte('%') + p.buf.Write(percentBangBytes) p.add(verb) p.buf.Write(panicBytes) p.panicking = true - p.printField(err, 'v', false, false, 0) + p.printArg(err, 'v', false, false, 0) p.panicking = false p.buf.WriteByte(')') } @@ -670,10 +674,10 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString return } // Is it a Formatter? - if formatter, ok := p.field.(Formatter); ok { + if formatter, ok := p.arg.(Formatter); ok { handled = true wasString = false - defer p.catchPanic(p.field, verb) + defer p.catchPanic(p.arg, verb) formatter.Format(p, verb) return } @@ -682,13 +686,13 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString p.fmt.plus = false } - // If we're doing Go syntax and the field knows how to supply it, take care of it now. + // 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 stringer, ok := p.field.(GoStringer); ok { + if stringer, ok := p.arg.(GoStringer); ok { wasString = false handled = true - defer p.catchPanic(p.field, verb) + defer p.catchPanic(p.arg, verb) // Print the result of GoString unadorned. p.fmtString(stringer.GoString(), 's', false) return @@ -703,19 +707,19 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString // The duplication in the bodies is necessary: // setting wasString and handled, and deferring catchPanic, // must happen before calling the method. - switch v := p.field.(type) { + switch v := p.arg.(type) { case error: wasString = false handled = true - defer p.catchPanic(p.field, verb) - p.printField(v.Error(), verb, plus, false, depth) + defer p.catchPanic(p.arg, verb) + p.printArg(v.Error(), verb, plus, false, depth) return case Stringer: wasString = false handled = true - defer p.catchPanic(p.field, verb) - p.printField(v.String(), verb, plus, false, depth) + defer p.catchPanic(p.arg, verb) + p.printArg(v.String(), verb, plus, false, depth) return } } @@ -724,11 +728,11 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString return } -func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) { - p.field = field +func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) { + p.arg = arg p.value = reflect.Value{} - if field == nil { + if arg == nil { if verb == 'T' || verb == 'v' { p.fmt.pad(nilAngleBytes) } else { @@ -741,10 +745,10 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth // %T (the value's type) and %p (its address) are special; we always do them first. switch verb { case 'T': - p.printField(reflect.TypeOf(field).String(), 's', false, false, 0) + p.printArg(reflect.TypeOf(arg).String(), 's', false, false, 0) return false case 'p': - p.fmtPointer(reflect.ValueOf(field), verb, goSyntax) + p.fmtPointer(reflect.ValueOf(arg), verb, goSyntax) return false } @@ -762,7 +766,7 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth } // Some types can be done without reflection. - switch f := field.(type) { + switch f := arg.(type) { case bool: p.fmtBool(f, verb) case float32: @@ -770,7 +774,7 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth case float64: p.fmtFloat64(f, verb) case complex64: - p.fmtComplex64(complex64(f), verb) + p.fmtComplex64(f, verb) case complex128: p.fmtComplex128(f, verb) case int: @@ -806,17 +810,17 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth p.fmt.plus = oldPlus p.fmt.sharp = oldSharp // If the type is not simple, it might have methods. - if wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled { - return wasString + if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled { + return isString } // Need to use reflection - return p.printReflectValue(reflect.ValueOf(field), verb, plus, goSyntax, depth) + return p.printReflectValue(reflect.ValueOf(arg), verb, plus, goSyntax, depth) } - p.field = nil + p.arg = nil return } -// printValue is like printField but starts with a reflect value, not an interface{} value. +// 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) { if !value.IsValid() { if verb == 'T' || verb == 'v' { @@ -831,7 +835,7 @@ 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.printField(value.Type().String(), 's', false, false, 0) + p.printArg(value.Type().String(), 's', false, false, 0) return false case 'p': p.fmtPointer(value, verb, goSyntax) @@ -839,19 +843,19 @@ func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, dep } // Handle values with special methods. - // Call always, even when field == nil, because handleMethods clears p.fmt.plus for us. - p.field = nil // Make sure it's cleared, for safety. + // Call always, even when arg == nil, because handleMethods clears p.fmt.plus for us. + p.arg = nil // Make sure it's cleared, for safety. if value.CanInterface() { - p.field = value.Interface() + p.arg = value.Interface() } - if wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled { - return wasString + if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled { + return isString } return p.printReflectValue(value, verb, plus, goSyntax, depth) } -// printReflectValue is the fallback for both printField and printValue. +// 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) { oldValue := p.value @@ -863,18 +867,18 @@ 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(uint64(f.Uint()), verb, goSyntax) + p.fmtUint64(f.Uint(), verb, goSyntax) case reflect.Float32, reflect.Float64: if f.Type().Size() == 4 { p.fmtFloat32(float32(f.Float()), verb) } else { - p.fmtFloat64(float64(f.Float()), verb) + p.fmtFloat64(f.Float(), verb) } case reflect.Complex64, reflect.Complex128: if f.Type().Size() == 8 { p.fmtComplex64(complex64(f.Complex()), verb) } else { - p.fmtComplex128(complex128(f.Complex()), verb) + p.fmtComplex128(f.Complex(), verb) } case reflect.String: p.fmtString(f.String(), verb, goSyntax) @@ -1015,20 +1019,59 @@ BigSwitch: return wasString } -// intFromArg gets the fieldnumth element of a. On return, isInt reports whether the argument has type int. -func intFromArg(a []interface{}, end, i, fieldnum int) (num int, isInt bool, newi, newfieldnum int) { - newi, newfieldnum = end, fieldnum - if i < end && fieldnum < len(a) { - num, isInt = a[fieldnum].(int) - newi, newfieldnum = i+1, fieldnum+1 +// intFromArg gets the argNumth element of a. On return, isInt reports whether the argument has type int. +func intFromArg(a []interface{}, argNum int) (num int, isInt bool, newArgNum int) { + newArgNum = argNum + if argNum < len(a) { + num, isInt = a[argNum].(int) + newArgNum = argNum + 1 } return } +// parseArgNumber returns the value of the bracketed number, minus 1 +// (explicit argument numbers are one-indexed but we want zero-indexed). +// The opening bracket is known to be present at format[0]. +// The returned values are the index, the number of bytes to consume +// up to the closing paren, if present, and whether the number parsed +// ok. The bytes to consume will be 1 if no closing paren is present. +func parseArgNumber(format string) (index int, wid int, ok bool) { + // Find closing bracket. + for i := 1; i < len(format); i++ { + if format[i] == ']' { + width, ok, newi := parsenum(format, 1, i) + if !ok || newi != i { + return 0, i + 1, false + } + return width - 1, i + 1, true // arg numbers are one-indexed and skip paren. + } + } + return 0, 1, false +} + +// argNumber returns the next argument to evaluate, which is either the value of the passed-in +// argNum or the value of the bracketed integer that begins format[i:]. It also returns +// the new value of i, that is, the index of the next byte of the format to process. +func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum, newi int, found bool) { + if len(format) <= i || format[i] != '[' { + return argNum, i, false + } + p.reordered = true + index, wid, ok := parseArgNumber(format[i:]) + if ok && 0 <= index && index < numArgs { + return index, i + wid, true + } + p.goodArgNum = false + return argNum, i + wid, true +} + func (p *pp) doPrintf(format string, a []interface{}) { end := len(format) - fieldnum := 0 // we process one field per non-trivial format + argNum := 0 // we process one argument per non-trivial format + afterIndex := false // previous item in format was an index like [3]. + p.reordered = false for i := 0; i < end; { + p.goodArgNum = true lasti := i for i < end && format[i] != '%' { i++ @@ -1043,7 +1086,8 @@ func (p *pp) doPrintf(format string, a []interface{}) { // Process one verb i++ - // flags and widths + + // Do we have flags? p.fmt.clearflags() F: for ; i < end; i++ { @@ -1062,30 +1106,52 @@ func (p *pp) doPrintf(format string, a []interface{}) { break F } } - // do we have width? + + // Do we have an explicit argument index? + argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a)) + + // Do we have width? if i < end && format[i] == '*' { - p.fmt.wid, p.fmt.widPresent, i, fieldnum = intFromArg(a, end, i, fieldnum) + i++ + p.fmt.wid, p.fmt.widPresent, argNum = intFromArg(a, argNum) if !p.fmt.widPresent { p.buf.Write(badWidthBytes) } + afterIndex = false } else { p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end) + if afterIndex && p.fmt.widPresent { // "%[3]2d" + p.goodArgNum = false + } } - // do we have precision? + + // Do we have precision? if i+1 < end && format[i] == '.' { - if format[i+1] == '*' { - p.fmt.prec, p.fmt.precPresent, i, fieldnum = intFromArg(a, end, i+1, fieldnum) + i++ + if afterIndex { // "%[3].2d" + p.goodArgNum = false + } + argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a)) + if format[i] == '*' { + i++ + p.fmt.prec, p.fmt.precPresent, argNum = intFromArg(a, argNum) if !p.fmt.precPresent { p.buf.Write(badPrecBytes) } + afterIndex = false } else { - p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i+1, end) + p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i, end) if !p.fmt.precPresent { p.fmt.prec = 0 p.fmt.precPresent = true } } } + + if !afterIndex { + argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a)) + } + if i >= end { p.buf.Write(noVerbBytes) continue @@ -1097,30 +1163,38 @@ func (p *pp) doPrintf(format string, a []interface{}) { p.buf.WriteByte('%') // We ignore width and prec. continue } - if fieldnum >= len(a) { // out of operands - p.buf.WriteByte('%') + if !p.goodArgNum { + p.buf.Write(percentBangBytes) + p.add(c) + p.buf.Write(badIndexBytes) + continue + } else if argNum >= len(a) { // out of operands + p.buf.Write(percentBangBytes) p.add(c) p.buf.Write(missingBytes) continue } - field := a[fieldnum] - fieldnum++ + arg := a[argNum] + argNum++ goSyntax := c == 'v' && p.fmt.sharp plus := c == 'v' && p.fmt.plus - p.printField(field, c, plus, goSyntax, 0) + p.printArg(arg, c, plus, goSyntax, 0) } - if fieldnum < len(a) { + // Check for extra arguments unless the call accessed the arguments + // out of order, in which case it's too expensive to detect if they've all + // been used and arguably OK if they're not. + if !p.reordered && argNum < len(a) { p.buf.Write(extraBytes) - for ; fieldnum < len(a); fieldnum++ { - field := a[fieldnum] - if field != nil { - p.buf.WriteString(reflect.TypeOf(field).String()) + for ; argNum < len(a); argNum++ { + arg := a[argNum] + if arg != nil { + p.buf.WriteString(reflect.TypeOf(arg).String()) p.buf.WriteByte('=') } - p.printField(field, 'v', false, false, 0) - if fieldnum+1 < len(a) { + p.printArg(arg, 'v', false, false, 0) + if argNum+1 < len(a) { p.buf.Write(commaSpaceBytes) } } @@ -1130,17 +1204,17 @@ func (p *pp) doPrintf(format string, a []interface{}) { func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) { prevString := false - for fieldnum := 0; fieldnum < len(a); fieldnum++ { + for argNum := 0; argNum < len(a); argNum++ { p.fmt.clearflags() // always add spaces if we're doing Println - field := a[fieldnum] - if fieldnum > 0 { - isString := field != nil && reflect.TypeOf(field).Kind() == reflect.String + arg := a[argNum] + if argNum > 0 { + isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String if addspace || !isString && !prevString { p.buf.WriteByte(' ') } } - prevString = p.printField(field, 'v', false, false, 0) + prevString = p.printArg(arg, 'v', false, false, 0) } if addnewline { p.buf.WriteByte('\n') diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go index bf888c4..5b1be58 100644 --- a/libgo/go/fmt/scan.go +++ b/libgo/go/fmt/scan.go @@ -168,12 +168,12 @@ type ss struct { // ssave holds the parts of ss that need to be // saved and restored on recursive scans. type ssave struct { - validSave bool // is or was a part of an actual ss. - nlIsEnd bool // whether newline terminates scan - nlIsSpace bool // whether newline counts as white space - fieldLimit int // max value of ss.count for this field; fieldLimit <= limit - limit int // max value of ss.count. - maxWid int // width of this field. + validSave bool // is or was a part of an actual ss. + nlIsEnd bool // whether newline terminates scan + nlIsSpace bool // whether newline counts as white space + argLimit int // max value of ss.count for this arg; argLimit <= limit + limit int // max value of ss.count. + maxWid int // width of this arg. } // The Read method is only in ScanState so that ScanState @@ -192,7 +192,7 @@ func (s *ss) ReadRune() (r rune, size int, err error) { s.peekRune = -1 return } - if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.fieldLimit { + if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.argLimit { err = io.EOF return } @@ -389,7 +389,7 @@ func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) { s, ok := r.(*ss) if ok { old = s.ssave - s.limit = s.fieldLimit + s.limit = s.argLimit s.nlIsEnd = nlIsEnd || s.nlIsEnd s.nlIsSpace = nlIsSpace return @@ -407,7 +407,7 @@ func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) { s.peekRune = -1 s.atEOF = false s.limit = hugeWid - s.fieldLimit = hugeWid + s.argLimit = hugeWid s.maxWid = hugeWid s.validSave = true s.count = 0 @@ -437,6 +437,9 @@ func (s *ss) skipSpace(stopAtNewline bool) { if r == eof { return } + if r == '\r' && s.peek("\n") { + continue + } if r == '\n' { if stopAtNewline { break @@ -476,11 +479,6 @@ func (s *ss) token(skipSpace bool, f func(rune) bool) []byte { return s.buf } -// typeError indicates that the type of the operand did not match the format -func (s *ss) typeError(field interface{}, expected string) { - s.errorString("expected field of type pointer to " + expected + "; found " + reflect.TypeOf(field).String()) -} - var complexError = errors.New("syntax error scanning complex number") var boolError = errors.New("syntax error scanning boolean") @@ -781,7 +779,7 @@ func (s *ss) convertFloat(str string, n int) float64 { } s.error(err) } - n, err := strconv.Atoi(str[p+1:]) + m, err := strconv.Atoi(str[p+1:]) if err != nil { // Put full string into error. if e, ok := err.(*strconv.NumError); ok { @@ -789,7 +787,7 @@ func (s *ss) convertFloat(str string, n int) float64 { } s.error(err) } - return math.Ldexp(f, n) + return math.Ldexp(f, m) } f, err := strconv.ParseFloat(str, n) if err != nil { @@ -858,8 +856,7 @@ func (s *ss) quotedString() string { // In a legal backslash escape, no matter how long, only the character // immediately after the escape can itself be a backslash or quote. // Thus we only need to protect the first character after the backslash. - r := s.mustReadRune() - s.buf.WriteRune(r) + s.buf.WriteRune(s.mustReadRune()) } else if r == '"' { break } @@ -886,7 +883,7 @@ func (s *ss) hexDigit(d rune) int { case 'A', 'B', 'C', 'D', 'E', 'F': return 10 + digit - 'A' } - s.errorString("Scan: illegal hex digit") + s.errorString("illegal hex digit") return 0 } @@ -916,7 +913,7 @@ func (s *ss) hexString() string { s.buf.WriteByte(b) } if len(s.buf) == 0 { - s.errorString("Scan: no hex data for %x string") + s.errorString("no hex data for %x string") return "" } return string(s.buf) @@ -927,11 +924,11 @@ const floatVerbs = "beEfFgGv" const hugeWid = 1 << 30 // scanOne scans a single value, deriving the scanner from the type of the argument. -func (s *ss) scanOne(verb rune, field interface{}) { +func (s *ss) scanOne(verb rune, arg interface{}) { s.buf = s.buf[:0] var err error // If the parameter has its own Scan method, use that. - if v, ok := field.(Scanner); ok { + if v, ok := arg.(Scanner); ok { err = v.Scan(s, verb) if err != nil { if err == io.EOF { @@ -942,7 +939,7 @@ func (s *ss) scanOne(verb rune, field interface{}) { return } - switch v := field.(type) { + switch v := arg.(type) { case *bool: *v = s.scanBool(verb) case *complex64: @@ -995,7 +992,7 @@ func (s *ss) scanOne(verb rune, field interface{}) { val := reflect.ValueOf(v) ptr := val if ptr.Kind() != reflect.Ptr { - s.errorString("Scan: type not a pointer: " + val.Type().String()) + s.errorString("type not a pointer: " + val.Type().String()) return } switch v := ptr.Elem(); v.Kind() { @@ -1011,7 +1008,7 @@ func (s *ss) scanOne(verb rune, field interface{}) { // For now, can only handle (renamed) []byte. typ := v.Type() if typ.Elem().Kind() != reflect.Uint8 { - s.errorString("Scan: can't handle type: " + val.Type().String()) + s.errorString("can't scan type: " + val.Type().String()) } str := s.convertString(verb) v.Set(reflect.MakeSlice(typ, len(str), len(str))) @@ -1025,7 +1022,7 @@ func (s *ss) scanOne(verb rune, field interface{}) { case reflect.Complex64, reflect.Complex128: v.SetComplex(s.scanComplex(verb, v.Type().Bits())) default: - s.errorString("Scan: can't handle type: " + val.Type().String()) + s.errorString("can't scan type: " + val.Type().String()) } } } @@ -1046,8 +1043,8 @@ func errorHandler(errp *error) { // doScan does the real work for scanning without a format string. func (s *ss) doScan(a []interface{}) (numProcessed int, err error) { defer errorHandler(&err) - for _, field := range a { - s.scanOne('v', field) + for _, arg := range a { + s.scanOne('v', arg) numProcessed++ } // Check for newline if required. @@ -1058,7 +1055,7 @@ func (s *ss) doScan(a []interface{}) (numProcessed int, err error) { break } if !isSpace(r) { - s.errorString("Scan: expected newline") + s.errorString("expected newline") break } } @@ -1144,9 +1141,9 @@ func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err erro if !widPresent { s.maxWid = hugeWid } - s.fieldLimit = s.limit - if f := s.count + s.maxWid; f < s.fieldLimit { - s.fieldLimit = f + s.argLimit = s.limit + if f := s.count + s.maxWid; f < s.argLimit { + s.argLimit = f } c, w := utf8.DecodeRuneInString(format[i:]) @@ -1156,11 +1153,11 @@ func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err erro s.errorString("too few operands for format %" + format[i-w:]) break } - field := a[numProcessed] + arg := a[numProcessed] - s.scanOne(c, field) + s.scanOne(c, arg) numProcessed++ - s.fieldLimit = s.limit + s.argLimit = s.limit } if numProcessed < len(a) { s.errorString("too many operands") diff --git a/libgo/go/fmt/scan_test.go b/libgo/go/fmt/scan_test.go index 4e2c0fe..d903f0c 100644 --- a/libgo/go/fmt/scan_test.go +++ b/libgo/go/fmt/scan_test.go @@ -54,7 +54,6 @@ var ( float32Val float32 float64Val float64 stringVal string - stringVal1 string bytesVal []byte runeVal rune complex64Val complex64 @@ -192,6 +191,10 @@ var scanTests = []ScanTest{ {"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)}, {"hello\n", &stringVal, "hello"}, + // Carriage-return followed by newline. (We treat \r\n as \n always.) + {"hello\r\n", &stringVal, "hello"}, + {"27\r\n", &uint8Val, uint8(27)}, + // Renamed types {"true\n", &renamedBoolVal, renamedBool(true)}, {"F\n", &renamedBoolVal, renamedBool(false)}, |