@@ -59,52 +59,7 @@ import (
5959type stack []uintptr
6060
6161func (s stack ) Location () (string , int ) {
62- pc := s [0 ] - 1
63- fn := runtime .FuncForPC (pc )
64- if fn == nil {
65- return "unknown" , 0
66- }
67-
68- file , line := fn .FileLine (pc )
69-
70- // Here we want to get the source file path relative to the compile time
71- // GOPATH. As of Go 1.6.x there is no direct way to know the compiled
72- // GOPATH at runtime, but we can infer the number of path segments in the
73- // GOPATH. We note that fn.Name() returns the function name qualified by
74- // the import path, which does not include the GOPATH. Thus we can trim
75- // segments from the beginning of the file path until the number of path
76- // separators remaining is one more than the number of path separators in
77- // the function name. For example, given:
78- //
79- // GOPATH /home/user
80- // file /home/user/src/pkg/sub/file.go
81- // fn.Name() pkg/sub.Type.Method
82- //
83- // We want to produce:
84- //
85- // pkg/sub/file.go
86- //
87- // From this we can easily see that fn.Name() has one less path separator
88- // than our desired output. We count separators from the end of the file
89- // path until it finds two more than in the function name and then move
90- // one character forward to preserve the initial path segment without a
91- // leading separator.
92- const sep = "/"
93- goal := strings .Count (fn .Name (), sep ) + 2
94- i := len (file )
95- for n := 0 ; n < goal ; n ++ {
96- i = strings .LastIndex (file [:i ], sep )
97- if i == - 1 {
98- // not enough separators found, set i so that the slice expression
99- // below leaves file unmodified
100- i = - len (sep )
101- break
102- }
103- }
104- // get back to 0 or trim the leading separator
105- file = file [i + len (sep ):]
106-
107- return file , line
62+ return location (s [0 ] - 1 )
10863}
10964
11065// New returns an error that formats as the given text.
@@ -241,3 +196,52 @@ func callers() stack {
241196 n := runtime .Callers (3 , pcs [:])
242197 return pcs [0 :n ]
243198}
199+
200+ // location returns the source file and line matching pc.
201+ func location (pc uintptr ) (string , int ) {
202+ fn := runtime .FuncForPC (pc )
203+ if fn == nil {
204+ return "unknown" , 0
205+ }
206+
207+ file , line := fn .FileLine (pc )
208+
209+ // Here we want to get the source file path relative to the compile time
210+ // GOPATH. As of Go 1.6.x there is no direct way to know the compiled
211+ // GOPATH at runtime, but we can infer the number of path segments in the
212+ // GOPATH. We note that fn.Name() returns the function name qualified by
213+ // the import path, which does not include the GOPATH. Thus we can trim
214+ // segments from the beginning of the file path until the number of path
215+ // separators remaining is one more than the number of path separators in
216+ // the function name. For example, given:
217+ //
218+ // GOPATH /home/user
219+ // file /home/user/src/pkg/sub/file.go
220+ // fn.Name() pkg/sub.Type.Method
221+ //
222+ // We want to produce:
223+ //
224+ // pkg/sub/file.go
225+ //
226+ // From this we can easily see that fn.Name() has one less path separator
227+ // than our desired output. We count separators from the end of the file
228+ // path until it finds two more than in the function name and then move
229+ // one character forward to preserve the initial path segment without a
230+ // leading separator.
231+ const sep = "/"
232+ goal := strings .Count (fn .Name (), sep ) + 2
233+ i := len (file )
234+ for n := 0 ; n < goal ; n ++ {
235+ i = strings .LastIndex (file [:i ], sep )
236+ if i == - 1 {
237+ // not enough separators found, set i so that the slice expression
238+ // below leaves file unmodified
239+ i = - len (sep )
240+ break
241+ }
242+ }
243+ // get back to 0 or trim the leading separator
244+ file = file [i + len (sep ):]
245+
246+ return file , line
247+ }
0 commit comments