]> Cypherpunks repositories - gostls13.git/commitdiff
fmt.Printf: introduce notation for random access to arguments.
authorRob Pike <r@golang.org>
Fri, 24 May 2013 22:49:26 +0000 (15:49 -0700)
committerRob Pike <r@golang.org>
Fri, 24 May 2013 22:49:26 +0000 (15:49 -0700)
This text is added to doc.go:

        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".

The notation chosen differs from that in C, but I believe it's easier to read
and to remember (we're indexing the arguments), and compatibility with
C's printf was never a strong goal anyway.

While we're here, change the word "field" to "arg" or "argument" in the
code; it was being misused and was confusing.

R=rsc, bradfitz, rogpeppe, minux.ma, peter.armitage
CC=golang-dev
https://golang.org/cl/9680043

doc/go1.2.txt
src/pkg/fmt/doc.go
src/pkg/fmt/fmt_test.go
src/pkg/fmt/print.go
src/pkg/fmt/scan.go

index 844e367a0a4083bf04b97270e97650e5cf0d249d..01b98bec4cdaea3e25380c4f45b9b012758ffa17 100644 (file)
@@ -8,4 +8,5 @@ Please keep the descriptions to a single line, starting with the
 package or cmd/xxx directory name, and ending in a CL number.
 Please keep the list sorted (as in sort.Strings of the lines).
 
+fmt: indexed access to arguments in Printf etc. (CL 9680043).
 io: Copy prioritizes WriterTo over ReaderFrom (CL 9462044).
index b8dd995c77b88529e0246e39bd0310ab2a0bf579..a0c6795d81669d8f1da62cc60a2a15d51a6295ed 100644 (file)
        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
                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 out-of-range argument index: %!(BADARGNUM)
+                       Printf("%*[2]d", 7):       %d(BADARGNUM)
 
        All errors begin with the string "%!" followed sometimes
        by a single character (the verb) and end with a parenthesized
index 20b723a99bb48913631ee5464a1000fd31dfd0d3..a121c9c2480081ae3fefa294dae2a35ddf370402 100644 (file)
@@ -110,7 +110,7 @@ var bslice = barray[:]
 
 var b byte
 
-var fmttests = []struct {
+var fmtTests = []struct {
        fmt string
        val interface{}
        out string
@@ -503,7 +503,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 +539,42 @@ 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"},
+       {"%[3]*[2].*[1]f", SE{12.0, 2, 6}, " 12.00"},
+       {"%[1]*[2].*[3]f", SE{6, 2, 12.0}, " 12.00"},
+       // 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(BADARGNUM)"},
+       {"%[-3]d", SE{2, 1}, "%d(BADARGNUM)"},
+       {"%[x]d", SE{2, 1}, "%d(BADARGNUM)"},
+       {"%[23]d", SE{2, 1}, "%d(BADARGNUM)"},
+       {"%[3]", SE{2, 1}, "%!(NOVERB)"},
+       {"%d %d %d %#[1]o %#o %#o %#o", SE{11, 12, 13}, "11 12 13 013 014 015 %o(MISSING)"},
+}
+
+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("")
index 5f37fd1208522355a4a802041cac1a0c3c4460ef..58ffe216e9e5973512aa9db72eabccf184d623c3 100644 (file)
@@ -22,6 +22,7 @@ var (
        nilBytes        = []byte("nil")
        mapBytes        = []byte("map[")
        missingBytes    = []byte("(MISSING)")
+       badArgNum       = []byte("(BADARGNUM)")
        panicBytes      = []byte("(PANIC=")
        extraBytes      = []byte("%!(EXTRA ")
        irparenBytes    = []byte("i)")
@@ -109,13 +110,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 last reordering directive was valid.
+       goodArgNum bool
+       runeBuf    [utf8.UTFMax]byte
+       fmt        fmt
 }
 
 // A cache holds a set of reusable objects.
@@ -170,7 +175,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 +217,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 +251,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 +283,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 +305,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 +345,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('=')
@@ -566,7 +571,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('}')
@@ -640,26 +645,26 @@ var (
        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.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 +675,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 +687,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 +708,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 +729,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 +746,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 +767,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:
@@ -810,13 +815,13 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
                        return wasString
                }
                // 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 +836,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,10 +844,10 @@ 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
@@ -851,7 +856,7 @@ func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, dep
        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
@@ -1015,19 +1020,57 @@ 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{}, end, i, argNum int) (num int, isInt bool, newi, newArgNum int) {
+       newi, newArgNum = end, argNum
+       if i < end && argNum < len(a) {
+               num, isInt = a[argNum].(int)
+               newi, newArgNum = i+1, 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 parenthesis
+       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) {
+       p.goodArgNum = true
+       if len(format) <= i || format[i] != '[' {
+               return argNum, i
+       }
+       p.reordered = true
+       index, wid, ok := parseArgNumber(format[i:])
+       if ok && 0 <= index && index < numArgs {
+               return index, i + wid
+       }
+       p.goodArgNum = false
+       return argNum, i + wid
+}
+
 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
+       p.reordered = false
        for i := 0; i < end; {
                lasti := i
                for i < end && format[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,22 +1106,29 @@ func (p *pp) doPrintf(format string, a []interface{}) {
                                break F
                        }
                }
-               // do we have width?
+
+               // Do we have an explicit argument index?
+               argNum, i = 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)
+                       p.fmt.wid, p.fmt.widPresent, i, argNum = intFromArg(a, end, i, argNum)
                        if !p.fmt.widPresent {
                                p.buf.Write(badWidthBytes)
                        }
+                       argNum, i = p.argNumber(argNum, format, i, len(a)) // We consumed []; another can follow here.
                } else {
                        p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end)
                }
-               // 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)
+                               p.fmt.prec, p.fmt.precPresent, i, argNum = intFromArg(a, end, i+1, argNum)
                                if !p.fmt.precPresent {
                                        p.buf.Write(badPrecBytes)
                                }
+                               argNum, i = p.argNumber(argNum, format, i, len(a)) // We consumed []; another can follow here.
                        } else {
                                p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i+1, end)
                                if !p.fmt.precPresent {
@@ -1097,30 +1148,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
+               if !p.goodArgNum {
+                       p.buf.WriteByte('%')
+                       p.add(c)
+                       p.buf.Write(badArgNum)
+                       continue
+               } else if argNum >= len(a) { // out of operands
                        p.buf.WriteByte('%')
                        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 +1189,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')
index bf888c4d88c5edd72e9fbfd6d8b2b38095c599d4..d2d7867da7850353b5b2f97cee0b0f8f3545990c 100644 (file)
@@ -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
@@ -477,8 +477,8 @@ func (s *ss) token(skipSpace bool, f func(rune) bool) []byte {
 }
 
 // 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())
+func (s *ss) typeError(arg interface{}, expected string) {
+       s.errorString("expected argument of type pointer to " + expected + "; found " + reflect.TypeOf(arg).String())
 }
 
 var complexError = errors.New("syntax error scanning complex number")
@@ -927,11 +927,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 +942,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:
@@ -1046,8 +1046,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.
@@ -1144,9 +1144,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 +1156,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")