podman

Форк
0
177 строк · 4.1 Кб
1
package errors
2

3
import (
4
	"fmt"
5
	"io"
6
	"path"
7
	"runtime"
8
	"strconv"
9
	"strings"
10
)
11

12
// Frame represents a program counter inside a stack frame.
13
// For historical reasons if Frame is interpreted as a uintptr
14
// its value represents the program counter + 1.
15
type Frame uintptr
16

17
// pc returns the program counter for this frame;
18
// multiple frames may have the same PC value.
19
func (f Frame) pc() uintptr { return uintptr(f) - 1 }
20

21
// file returns the full path to the file that contains the
22
// function for this Frame's pc.
23
func (f Frame) file() string {
24
	fn := runtime.FuncForPC(f.pc())
25
	if fn == nil {
26
		return "unknown"
27
	}
28
	file, _ := fn.FileLine(f.pc())
29
	return file
30
}
31

32
// line returns the line number of source code of the
33
// function for this Frame's pc.
34
func (f Frame) line() int {
35
	fn := runtime.FuncForPC(f.pc())
36
	if fn == nil {
37
		return 0
38
	}
39
	_, line := fn.FileLine(f.pc())
40
	return line
41
}
42

43
// name returns the name of this function, if known.
44
func (f Frame) name() string {
45
	fn := runtime.FuncForPC(f.pc())
46
	if fn == nil {
47
		return "unknown"
48
	}
49
	return fn.Name()
50
}
51

52
// Format formats the frame according to the fmt.Formatter interface.
53
//
54
//    %s    source file
55
//    %d    source line
56
//    %n    function name
57
//    %v    equivalent to %s:%d
58
//
59
// Format accepts flags that alter the printing of some verbs, as follows:
60
//
61
//    %+s   function name and path of source file relative to the compile time
62
//          GOPATH separated by \n\t (<funcname>\n\t<path>)
63
//    %+v   equivalent to %+s:%d
64
func (f Frame) Format(s fmt.State, verb rune) {
65
	switch verb {
66
	case 's':
67
		switch {
68
		case s.Flag('+'):
69
			io.WriteString(s, f.name())
70
			io.WriteString(s, "\n\t")
71
			io.WriteString(s, f.file())
72
		default:
73
			io.WriteString(s, path.Base(f.file()))
74
		}
75
	case 'd':
76
		io.WriteString(s, strconv.Itoa(f.line()))
77
	case 'n':
78
		io.WriteString(s, funcname(f.name()))
79
	case 'v':
80
		f.Format(s, 's')
81
		io.WriteString(s, ":")
82
		f.Format(s, 'd')
83
	}
84
}
85

86
// MarshalText formats a stacktrace Frame as a text string. The output is the
87
// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs.
88
func (f Frame) MarshalText() ([]byte, error) {
89
	name := f.name()
90
	if name == "unknown" {
91
		return []byte(name), nil
92
	}
93
	return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil
94
}
95

96
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
97
type StackTrace []Frame
98

99
// Format formats the stack of Frames according to the fmt.Formatter interface.
100
//
101
//    %s	lists source files for each Frame in the stack
102
//    %v	lists the source file and line number for each Frame in the stack
103
//
104
// Format accepts flags that alter the printing of some verbs, as follows:
105
//
106
//    %+v   Prints filename, function, and line number for each Frame in the stack.
107
func (st StackTrace) Format(s fmt.State, verb rune) {
108
	switch verb {
109
	case 'v':
110
		switch {
111
		case s.Flag('+'):
112
			for _, f := range st {
113
				io.WriteString(s, "\n")
114
				f.Format(s, verb)
115
			}
116
		case s.Flag('#'):
117
			fmt.Fprintf(s, "%#v", []Frame(st))
118
		default:
119
			st.formatSlice(s, verb)
120
		}
121
	case 's':
122
		st.formatSlice(s, verb)
123
	}
124
}
125

126
// formatSlice will format this StackTrace into the given buffer as a slice of
127
// Frame, only valid when called with '%s' or '%v'.
128
func (st StackTrace) formatSlice(s fmt.State, verb rune) {
129
	io.WriteString(s, "[")
130
	for i, f := range st {
131
		if i > 0 {
132
			io.WriteString(s, " ")
133
		}
134
		f.Format(s, verb)
135
	}
136
	io.WriteString(s, "]")
137
}
138

139
// stack represents a stack of program counters.
140
type stack []uintptr
141

142
func (s *stack) Format(st fmt.State, verb rune) {
143
	switch verb {
144
	case 'v':
145
		switch {
146
		case st.Flag('+'):
147
			for _, pc := range *s {
148
				f := Frame(pc)
149
				fmt.Fprintf(st, "\n%+v", f)
150
			}
151
		}
152
	}
153
}
154

155
func (s *stack) StackTrace() StackTrace {
156
	f := make([]Frame, len(*s))
157
	for i := 0; i < len(f); i++ {
158
		f[i] = Frame((*s)[i])
159
	}
160
	return f
161
}
162

163
func callers() *stack {
164
	const depth = 32
165
	var pcs [depth]uintptr
166
	n := runtime.Callers(3, pcs[:])
167
	var st stack = pcs[0:n]
168
	return &st
169
}
170

171
// funcname removes the path prefix component of a function's name reported by func.Name().
172
func funcname(name string) string {
173
	i := strings.LastIndex(name, "/")
174
	name = name[i+1:]
175
	i = strings.Index(name, ".")
176
	return name[i+1:]
177
}
178

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.