blob: c0a66ba84de71b6111f645b7816902c3c4e672f1 [file] [log] [blame]
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package obj
import (
"cmd/internal/src"
"path/filepath"
)
// AbsFile returns the absolute filename for file in the given directory.
// It also removes a leading pathPrefix, or else rewrites a leading $GOROOT
// prefix to the literal "$GOROOT".
// If the resulting path is the empty string, the result is "??".
func AbsFile(dir, file, pathPrefix string) string {
abs := file
if dir != "" && !filepath.IsAbs(file) {
abs = filepath.Join(dir, file)
}
if pathPrefix != "" && hasPathPrefix(abs, pathPrefix) {
if abs == pathPrefix {
abs = ""
} else {
abs = abs[len(pathPrefix)+1:]
}
} else if hasPathPrefix(abs, GOROOT) {
abs = "$GOROOT" + abs[len(GOROOT):]
}
if abs == "" {
abs = "??"
}
return filepath.Clean(abs)
}
// Does s have t as a path prefix?
// That is, does s == t or does s begin with t followed by a slash?
// For portability, we allow ASCII case folding, so that hasPathPrefix("a/b/c", "A/B") is true.
// Similarly, we allow slash folding, so that hasPathPrefix("a/b/c", "a\\b") is true.
// We do not allow full Unicode case folding, for fear of causing more confusion
// or harm than good. (For an example of the kinds of things that can go wrong,
// see http://article.gmane.org/gmane.linux.kernel/1853266.)
func hasPathPrefix(s string, t string) bool {
if len(t) > len(s) {
return false
}
var i int
for i = 0; i < len(t); i++ {
cs := int(s[i])
ct := int(t[i])
if 'A' <= cs && cs <= 'Z' {
cs += 'a' - 'A'
}
if 'A' <= ct && ct <= 'Z' {
ct += 'a' - 'A'
}
if cs == '\\' {
cs = '/'
}
if ct == '\\' {
ct = '/'
}
if cs != ct {
return false
}
}
return i >= len(s) || s[i] == '/' || s[i] == '\\'
}
// AddImport adds a package to the list of imported packages.
func (ctxt *Link) AddImport(pkg string) {
ctxt.Imports = append(ctxt.Imports, pkg)
}
func linkgetlineFromPos(ctxt *Link, xpos src.XPos) (f *LSym, l int32) {
pos := ctxt.PosTable.Pos(xpos)
filename := pos.AbsFilename()
if !pos.IsKnown() || filename == "" {
return Linklookup(ctxt, "??", HistVersion), 0
}
// TODO(gri) Should this use relative or absolute line number?
return Linklookup(ctxt, filename, HistVersion), int32(pos.RelLine())
}
func fieldtrack(ctxt *Link, cursym *LSym) {
p := cursym.Text
if p == nil || p.Link == nil { // handle external functions and ELF section symbols
return
}
ctxt.Cursym = cursym
for ; p != nil; p = p.Link {
if p.As == AUSEFIELD {
r := Addrel(ctxt.Cursym)
r.Off = 0
r.Siz = 0
r.Sym = p.From.Sym
r.Type = R_USEFIELD
}
}
}