Skip gnat.dg/prot7.adb on hppa.
[official-gcc.git] / libgo / go / golang.org / x / xerrors / adaptor.go
blob4317f2483313167ef4577dc668e3a7270066f6d6
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package xerrors
7 import (
8 "bytes"
9 "fmt"
10 "io"
11 "reflect"
12 "strconv"
15 // FormatError calls the FormatError method of f with an errors.Printer
16 // configured according to s and verb, and writes the result to s.
17 func FormatError(f Formatter, s fmt.State, verb rune) {
18 // Assuming this function is only called from the Format method, and given
19 // that FormatError takes precedence over Format, it cannot be called from
20 // any package that supports errors.Formatter. It is therefore safe to
21 // disregard that State may be a specific printer implementation and use one
22 // of our choice instead.
24 // limitations: does not support printing error as Go struct.
26 var (
27 sep = " " // separator before next error
28 p = &state{State: s}
29 direct = true
32 var err error = f
34 switch verb {
35 // Note that this switch must match the preference order
36 // for ordinary string printing (%#v before %+v, and so on).
38 case 'v':
39 if s.Flag('#') {
40 if stringer, ok := err.(fmt.GoStringer); ok {
41 io.WriteString(&p.buf, stringer.GoString())
42 goto exit
44 // proceed as if it were %v
45 } else if s.Flag('+') {
46 p.printDetail = true
47 sep = "\n - "
49 case 's':
50 case 'q', 'x', 'X':
51 // Use an intermediate buffer in the rare cases that precision,
52 // truncation, or one of the alternative verbs (q, x, and X) are
53 // specified.
54 direct = false
56 default:
57 p.buf.WriteString("%!")
58 p.buf.WriteRune(verb)
59 p.buf.WriteByte('(')
60 switch {
61 case err != nil:
62 p.buf.WriteString(reflect.TypeOf(f).String())
63 default:
64 p.buf.WriteString("<nil>")
66 p.buf.WriteByte(')')
67 io.Copy(s, &p.buf)
68 return
71 loop:
72 for {
73 switch v := err.(type) {
74 case Formatter:
75 err = v.FormatError((*printer)(p))
76 case fmt.Formatter:
77 v.Format(p, 'v')
78 break loop
79 default:
80 io.WriteString(&p.buf, v.Error())
81 break loop
83 if err == nil {
84 break
86 if p.needColon || !p.printDetail {
87 p.buf.WriteByte(':')
88 p.needColon = false
90 p.buf.WriteString(sep)
91 p.inDetail = false
92 p.needNewline = false
95 exit:
96 width, okW := s.Width()
97 prec, okP := s.Precision()
99 if !direct || (okW && width > 0) || okP {
100 // Construct format string from State s.
101 format := []byte{'%'}
102 if s.Flag('-') {
103 format = append(format, '-')
105 if s.Flag('+') {
106 format = append(format, '+')
108 if s.Flag(' ') {
109 format = append(format, ' ')
111 if okW {
112 format = strconv.AppendInt(format, int64(width), 10)
114 if okP {
115 format = append(format, '.')
116 format = strconv.AppendInt(format, int64(prec), 10)
118 format = append(format, string(verb)...)
119 fmt.Fprintf(s, string(format), p.buf.String())
120 } else {
121 io.Copy(s, &p.buf)
125 var detailSep = []byte("\n ")
127 // state tracks error printing state. It implements fmt.State.
128 type state struct {
129 fmt.State
130 buf bytes.Buffer
132 printDetail bool
133 inDetail bool
134 needColon bool
135 needNewline bool
138 func (s *state) Write(b []byte) (n int, err error) {
139 if s.printDetail {
140 if len(b) == 0 {
141 return 0, nil
143 if s.inDetail && s.needColon {
144 s.needNewline = true
145 if b[0] == '\n' {
146 b = b[1:]
149 k := 0
150 for i, c := range b {
151 if s.needNewline {
152 if s.inDetail && s.needColon {
153 s.buf.WriteByte(':')
154 s.needColon = false
156 s.buf.Write(detailSep)
157 s.needNewline = false
159 if c == '\n' {
160 s.buf.Write(b[k:i])
161 k = i + 1
162 s.needNewline = true
165 s.buf.Write(b[k:])
166 if !s.inDetail {
167 s.needColon = true
169 } else if !s.inDetail {
170 s.buf.Write(b)
172 return len(b), nil
175 // printer wraps a state to implement an xerrors.Printer.
176 type printer state
178 func (s *printer) Print(args ...interface{}) {
179 if !s.inDetail || s.printDetail {
180 fmt.Fprint((*state)(s), args...)
184 func (s *printer) Printf(format string, args ...interface{}) {
185 if !s.inDetail || s.printDetail {
186 fmt.Fprintf((*state)(s), format, args...)
190 func (s *printer) Detail() bool {
191 s.inDetail = true
192 return s.printDetail